With Winter ‘16, Salesforce introduced Lightning Experience. To provide a more streamlined user experience, you can now use Lightning Components and the Lightning Design System, as well as Visualforce. Using these tools you can create components that are reusable across applications and devices. These new options created an opportunity for customers and partners alike to revisit their applications to use this exciting new technology.
Back in December, our ISV Technical Enablement team launched a series of webinars around transitioning applications to Lightning. If you’re interested in developing Lightning Ready applications, watch the webinar recordings here.
However, with the initial launch of Lightning Experience developers had no way to build pages and components that dynamically react to the UI theme that the user is currently using.
Great news! With the Spring ‘16 release, Salesforce provides an easy and robust way for developers to detect the user’s UI theme.
UI Theme Detection can be done in one of two ways:
Why does Salesforce provide both the UITheme and UIThemeDisplayed methods? If users with Lightning Experience permissions are using an unsupported browser, they may experience Salesforce rendered in Salesforce Classic. If this happens, UITheme and UIThemeDisplayed return different values.
Note: Detecting the UI context via a server call is expensive, and should therefore be cached or carefully isolated into init or startup methods(see Apex utility sample below). This will prevent utility being called every time the component is rendered. If you only need to distinguish between Lightning Experience and Salesforce1, check out $Browser.
The string value stored in these variables or returned by these methods is one of the following:
Visualforce pages can use global variables to determine the UI theme in use without resorting to Apex. Look at the following Visualforce page.
<apex:page> <apex:stylesheet value="{!URLFOR($Resource.slds, 'assets/styles/salesforce-lightning-design-system-vf.css')}" /> <apex:outputPanel rendered="{!$User.UIThemeDisplayed == 'Theme3'}"> <apex:pageBlock title="Visualforce (Using standard Visualforce Components)" mode="detail"> <apex:outputLabel value="UI Theme Detection using Global Variables: {!$User.UIThemeDisplayed}"/> </apex:pageBlock> </apex:outputPanel> <apex:outputPanel rendered="{!$User.UIThemeDisplayed == 'Theme4d'}"> <div class="slds"> <div class="slds-card slds-card--empty"> <div class="slds-card__header slds-grid grid--flex-spread"> <h2 class="slds-text-heading--small slds-truncate">Visualforce (Using HTML + SLDS)</h2> </div> <div class="slds-card__body slds-p-horizontal--small"> <h3 class="slds-text-heading--small slds-p-top--large slds-p-bottom--large">UI Theme Detection using Global Variables: {!$User.UIThemeDisplayed}</h3> </div> </div> </div> </apex:outputPanel> </apex:page>
Using the global variable $User.UIThemeDisplayed, it detects which UI theme is being used. Based on the theme detected it dynamically renders a page that is adapted to either Salesforce Classic 2010 (using Visualforce Components) or Lightning Experience (using HTML + Lightning Design System). We could add other conditions (or a default condition) to capture additional scenarios.
Visualforce page rendered in Salesforce Classic:
Visualforce Page rendered in Lightning Experience:
You can’t determine the user’s UI theme directly within a Lightning Component because it only has access to a limited set of global values. You must implement an Apex server-side controller to provide this information.
We provide three pieces of sample code that demonstrate how you get the UI theme information you need into a component responsible for rendering UI. The basic flow is:
({ doInit : function(component, event) { var action = component.get("c.getUIThemeDescription"); action.setCallback(this, function(a) { component.set("v.Name", a.getReturnValue()); if(a.getReturnValue()=='Theme3' ||'Theme2'){ component.set("v.Desc", "Lightning Components can be rendered in Salesforce Classic using Lightning Components for Visualforce"); component.set("v.isLEX",false); }else if(a.getReturnValue()=='Theme4d'){ component.set("v.Desc", "Lightning Components can be rendered natively within Lightning Experience or, alternatively, within a Visualforce Page or within a Lightning Application."); component.set("v.isLEX",true); }else if(a.getReturnValue()=='Theme4t'){ component.set("v.Desc", "Salesforce1 Mobile natively supports Lightning Components"); component.set("v.isLEX",false); } }); $A.enqueueAction(action); } })
public with sharing class UIThemeController { @AuraEnabled public static String getUIThemeDescription() { String theme = UserInfo.getUiThemeDisplayed(); return theme; } }
<aura:component implements="flexipage:availableForAllPageTypes" controller="UIThemeController" access="global"> <aura:handler name="init" value="{!this}" action="{!c.doInit}" /> <aura:attribute name="Name" type="String" /> <aura:attribute name="isLEX" type="Boolean" /> <aura:attribute name="Desc" type="String" /> <div class="slds"> <div class="slds-card slds-card--empty"> <div class="slds-card__header slds-grid grid--flex-spread"> <h2 class="slds-text-heading--small slds-truncate">Lightning Component</h2> </div> <div class="slds-card__body slds-p-horizontal--small"> <h3 class="slds-text-heading--small slds-p-top--large slds-p-bottom--large">Detected Theme: {!v.Name}</h3> <h2 class="slds-text-heading--small slds-p-top--large slds-p-bottom--large">{!v.Desc}</h2> <aura:if isTrue="{!v.isLEX}"> <p>This text is only displayed in Lightning Experience</p> <aura:set attribute="else"> <p>This text is only displayed outside of Lightning Experience</p> </aura:set> </aura:if> </div> </div> </div> </aura:component>
If you want to try out the code yourself in Salesforce Classic, see Lightning Components for Visualforce.
Use the following recommendations and best practices for using UI Theme Detection in both Lightning Components and Visualforce.
We recommend that you use Lightning Components as much as possible as you build out new UI. You can use Lightning Components within Salesforce Classic by using the steps outlined here. You can also use Lightning Components natively in Salesforce1 Mobile and Lightning Experience.
Here are some use cases for UI Theme detection in Lightning Components:
Imagine you have a progress bar designed for Lightning Experience and another progress bar designed for Salesforce Classic. Putting your UI Theme detection at the facet level allows the facet to determine which of these lower-level components to invoke.
With the updated UI Theme Detection in Spring ‘16, you can now build Visualforce pages that dynamically adapt to Salesforce Classic, Lightning Experience, or Salesforce1 Mobile.
So why use UI Theme Detection for Visualforce pages now? The main advantage is that UI Theme Detection provides additional options:
Visualforce pages containing standard Visualforce components retain the Salesforce Classic look-and-feel, even when displayed in Lightning Experience. We expect this to remain true for the foreseeable future.
Customers who want pages that adapt to their user experience context can use UITheme detection to do so. You can use UITheme detection to render standard components when in Salesforce Classic, and to render new content based on HTML, JavaScript, and the Lightning Design System when in Lightning Experience. You can make use of the flexible Visualforce component, which takes styling well, or you can make use of Lightning Components for Visualforce. The latter option offers easy entry into the world of Lightning Components, if you’re looking a way to get started there.
If you plan to use the SLDS, we recommend keeping all the same html element IDs. Once the Lightning Design System is available on platform, your UI can access those tags automatically with the latest SLDS.
We continue to invest in making Lightning Experience and Salesforce1 Mobile the best they can be. With these changes to UITheme and UITThemeDisplayed, you can make your applications more dynamic and responsive to the various UI themes we are providing to customers. We look forward to seeing many more applications that use these exciting technologies!
John Belo & William Yeh are ISV Technical Evangelists here at Salesforce, they work with ISV Partners developing business solutions on the Salesforce AppCloud.
in/johnbelo | twitter: @johnbelo
in/yehwilliam | twitter: @wwilliam89