Lightning Components in Visualforce with Lightning Out

Lightning Out is a feature that extends Lightning Apps and acts as a bridge to surface Lightning Components in any remote web container. This means you can use your Lightning Components inside of an external site (i.e. Sharepoint or SAP), in a hybrid app built with the Mobile SDK, or even elsewhere in the App Cloud like on Heroku or in a Visualforce (VF) Page. This article covers the basics of how to put Lightning Components in Visualforce pages, and mitigate navigation for different app environments you might be using the component in simultaneously.

It’s almost time to Spring forward, and there are several handy developer features to check out. LeeAnne and I recently hosted the Spring ’16 Release Preview webinar for developers and admins, and one of the features I demoed that I’m most excited about is Lightning Out. With Lightning Out, your Lightning Components become significantly more powerful, and open up a range of new possibilities for Lightning.

What is Lightning Out?

Lightning Out is a feature that extends Lightning Apps. It acts as a bridge to surface Lightning Components in any remote web container. This means you can use your Lightning Components inside of an external site (i.e. Sharepoint or SAP), in a hybrid app built with the Mobile SDK, or even elsewhere in the App Cloud like on Heroku or in a Visualforce Page.

Using the Lightning Out JavaScript libraries you can embed Lightning Components in an app across domains and manage interactions between the component and the app directly in the DOM.

Try Lightning Components for Visualforce for Yourself

Lightning Out is currently in beta as of Spring ’16, but projected for general availability in the Summer. Lightning Components for Visualforce has been GA since Winter ’16 and is powered by Lightning Out.

I think this is pretty cool for a few reasons:

  1. You can build and use Lightning Components directly in Visualforce pages. This is not an iframe.
  2. You can develop components to be used in Classic, Salesforce1 (S1), and Lightning Experience (LEX) simultaneously.
  3. You can compose components on a Visualforce page, and integrate between components and/or the page on the client with JavaScript and Lightning Events.
  4. You can create new components in Lightning to add functionality to existing Visualforce pages.

Putting components onto a Visualforce page is relatively simple considering the majority of the integration has been abstracted away by Lightning Out. There are only three pieces to get this to work on a page: include the Lightning Out JavaScript libraries, specify which Lightning App to use that will designate component dependencies, and create the component on the page.

For apps outside of Force.com, you will additionally need to setup a cross origin resource sharing (CORS) whitelist URL setting for your external web app domain. You’ll also need to setup a Connected App with OAuth configured to the proper scopes.

How to Handle Navigation for Components Used in Classic, Salesforce1, and Lightning Experience

Right now there is no unified way to handle navigation between these three app environments. There are already suggested ways to navigate inside Visualforce in LEX or S1, but these suggestions do not cover the scenario of a component being used in all three environments simultaneously.

The first step is to detect the environment context. As of Spring ’16, you can use the global $User variable attributes around UITheme to detect your app environment context (Classic, S1, LEX) in a supported way. Once you detect the app environment, you can pass the context value in as an attribute for your component. In Visualforce it would look like this:

<body>
    <div id="myDivId"> 
    </div>
 
    <script>
        var myUserContext = "{!$User.UITheme}";
 
        $Lightning.use("c:myLightningApp", function() {
        $Lightning.createComponent(
            "c:myLightningComponent",
            { UserContext: myUserContext },
            "myDivId",
            function(cmp) {
                console.log('component created');
                console.log(cmp);
            });
        });
     </script>
 </body>

Passing in the context is pretty straight forward, and you can capture that value in an aura:attribute. Within my component’s JavaScript controller, I use that context variable to determine how to navigate for one of 3 scenarios: Visualforce in S1 or LEX, Visualforce in Classic, or a standalone component (no Visualforce) in S1 or LEX.

({
       contactSelected : function(component) {
           var context = component.get("v.UserContext");
 
           if(context != undefined) {
               if(context == 'Theme4t' || context == 'Theme4d') {
                   console.log('VF in S1 or LEX');
                   sforce.one.navigateToSObject(component.get("v.contact").Id);
               } else {
                   console.log('VF in Classic'); 
                   var contactId = component.get("v.contact").Id;
                   window.location.assign('/'+contactId);
               }
           } else {
               console.log('standalone Lightning Component');
               var event = $A.get("e.force:navigateToSObject");
               event.setParams({"recordId": component.get("v.contact").Id});
               event.fire();
           }
     }
})

With Visualforce inside of either S1 or LEX, you need to continue to use the sforce object to handle navigation. This will  maintain navigation breadcrumbs in the app and also properly navigate from the embedded Visualforce iframe. In classic, for pages you believe you will use in both classic and Lightning context, you should handle navigation with JavaScript rather than the PageReference class. Finally, for a standalone Lightning Component you can use Lightning Events to navigate.

 

Lightning Can Strike Many Times

With Lightning Out, your Lightning Components become significantly more powerful. Not only can you use Lightning Components in other Components or Lightning Apps, but you can surface them in practically any web container both on or off of the App Cloud.

About the Author

Samantha Ready is a senior developer evangelist at Salesforce, and has been at Salesforce for 5 years. During her tenure you might have seen her work in the Salesforce1 Dev Guide she co-authored, the Udacity course she taught centered around two passions (Music + Salesforce), or possibly from a Salesforce webinar or event. While her formal background is in robotics and engineering, she is has worked with all facets of the App Cloud with a strong focus on Force.com and front-end web development. When she isn’t coding, you might find Sam rock climbing, SCUBA diving, or snowboarding in this rainbowtastic onesie.

Leave your comments...

Lightning Components in Visualforce with Lightning Out