29

This isn't a question about the pros/cons of Lightning/Visualforce, but is a question about how to build custom UI for the period of time (a year or many years?) where some users/orgs have Lightning Experience turned on and other users/orgs don't.

Is the answer that you have to implement the custom UI twice, once in Lightning and once in Visualforce? Or is there a better approach?

(I am thinking particularly about managed packages that in principle should work in all sorts of orgs, but the problem also applies to once-off code in an org if only some users have Lightning Experience turned on.)

PS

The comment thread on the question below includes a link to Trailhead's Visualforce & Lightning Experience (Learn how to use Visualforce to customize your Lightning Experience) which looks like a good resource on how to get existing Visualforce to work in both classic and lightning environments. I'm getting the impression that building app UI that uses Lightning technology at all (client side MVC etc) will not be commercially rational (and there are certainly technical limitations too) for some time to come...

  • 1
    I would think the only way to do it would be to develop a VF using the LEX styling. Good question - followed – Eric Oct 20 '15 at 13:02
  • I believe it could be possible with the new feature introduced where we can use the VF page as an container for Angular.js and build and page which looks like lightening UI. Good Question!! – Nishant Singh Panwar Oct 20 '15 at 15:47
  • 1
    @NishantSinghPanwar I did have a quick play with this Showing a Lightning Component/App inside Visualforce Page. But firing up the Lightning app took a couple of extra seconds after the page loaded so separate Visualforce pages wrapping separate Lightning apps looks like a bad way to go. – Keith C Oct 20 '15 at 15:53
  • Did you got chance to look into details i.e. why it was slow? and can it be optimized? – AtulRajguru9 Oct 21 '15 at 5:36
  • @AtulRajguru9 I didn't investigate; I assume the problem is the extras steps of downloading JavaScript and executing it before any UI appears. – Keith C Oct 21 '15 at 7:43
10
+50

I just went through this exercise for a basic configuration page. Here is what I found out for a basic example:

  1. Liberal use of Javascript Remoting in place of submit elements (commandButton, commandLink, etc) along with calling actionfunctions in the handler to perform partial page refreshes

  2. Two VF Pages were required in order to show the page within Classic and inside LEX if you want the header or sidebar in classic:

     <apex:page showHeader="true" showSidebar="true">
         <apex:include page="LEXPAGENAME"/>
     </apex:page>
    
  3. You sill have to create your own JS to control the when and how to display elements like alerts / modals / etc. Some you can do with class names, other you have to use css. jQuery is helpful.

  4. I used a mix of mostly html tags with the occasional outputPanel with render attributes.

Doing it this way created a page that displayed and worked both inside of Classic and LEX as expected.

NOTE None of this used the Lightning Component framework and DID use the SLDS but it did "look" like lightning. If you are going to use Lightning Components you will have to do the lightning check and do double work to have it work in both UI's. Seems the interim is to make VF "Look" like lightning for now

Example of the same Wrapper page with embedded SLDS Page shown in both Classic then LEX

Classic enter image description here enter image description here enter image description here

LEX

enter image description here enter image description here enter image description here

For both UI's simply use the main wrapper page. In LEX it will strip off the header and sidebar automatically. So while you need a Wrapper page and a child page you only use the wrapper page in the tab..

  • Fyi Using Lightning Components: peterknolle.com/lightning-components-in-visualforce – Eric Nov 6 '15 at 23:17
  • FYI: I just tried using a component inside a vf page and none of the styles came across. Seems still better to use separate VF pages and components depending on the ui. Of course I could have been doing it wrong but the buttons looked like old ui buttons and none of the styles were applied. The same component in lightning looked fine.... – Eric Oct 13 '16 at 6:35
  • Is this still the "recommended" approach in Spring '17? Using the SLDS inside VF page, and avoiding Lightning Components? – smukov Apr 19 '17 at 19:33
  • @smukov - Depends on your goals. Obviously they are pushing Lightning components but styling with SLDS is still perfectly viable – Eric Apr 19 '17 at 19:34
  • Well, I'm starting my first Managed Package and this is my first stumbling block. The package is simple, among other things it will only have one "Settings" page and I need to make it "Lightning Ready", i.e., it needs to look native to Lightning, but it needs to work in Classic as well. It seems to me that your approach above is the only way to accomplish this at the moment, other than creating two completely separate pages from scratch, one with Lightning components, and other VF + SLDS, but that seems like doubling the work. – smukov Apr 19 '17 at 19:47
6

Sharing Visualforce Pages Between Classic and Lightning Experience

Salesforce recommends that, wherever possible, you create Visualforce pages that behave correctly whether they run in Salesforce Classic or Lightning Experience. The benefits in terms of reduced complexity in your organization’s code and configuration are obvious. And there are a number of contexts, such as Visualforce overrides of standard actions, where you don’t have a choice. An action override always uses the same page, whether you’re running in Salesforce Classic, Lightning Experience, or Salesforce1.

It’s perfectly reasonable, though, to want slightly or significantly different behavior or styling that’s based on the user experience context in which the page is running. In Winter ’16 the ability to detect the current user experience context is extremely limited, but it should cover the essentials.

Detecting the context

There’s a technique that has proven reasonably reliable, and covers the most essential use case. The technique depends on detecting the presence of a JavaScript utility object that’s unique to Lightning Experience and Salesforce1.

function isLightningExperienceOrSalesforce1() {
    return((typeof sforce != 'undefined') && sforce && (!!sforce.one));
}

if( isLightningExperienceOrSalesforce1() ) {
    // Do something for Lightning Experience
}
else {
    // Use classic Visualforce
}
  • 1
    So continue to write Visualforce but make it look OK and work OK in both Salesforce Classic and Lightning Experience? Is this the "Lightning Ready" approach? Sounds like the newer technology like Lightning Components has no place in that. – Keith C Oct 22 '15 at 16:15
  • 1
    @KeithC - Lightning Components are still very limited in where you can place them in the UI. If you aren't going live til after Summer 16, Lightning Components are PROBABLY (safe harbor) okay to use, but until then, you don't have them on record home, on object home, as actions/buttons from a record etc... Right now, they're only useful as standalone app tabs. – Christian Carter Oct 25 '15 at 17:52
1

My first recommendation will be to work with a javascript framework Angular.js or others to look good in both Lightning as well as Classic UI.

In case you can put extra effort of develpoment and testing for Classic UI and Lightning UI, you can use this work around (until there is a better solution). I've not tested it thoroughly, I am basing it on the url parameters which are different in lightning as compared to classic UI.

<apex:variable value="{!CONTAINS($CurrentPage.URL, 'lightning.force.com')}" var="isLightningMode"/>
    $CurrentPage.URL = {!$CurrentPage.URL} <br/>
    isLightningMode = {!isLightningMode} <br/>
    <apex:outputpanel layout="none" rendered="{!isLightningMode = false}">
        <!-- Classic UI - Code to display ui in Classic UI mode -->
        this is classic ui
    </apex:outputpanel>

    <apex:outputpanel layout="none" rendered="{!isLightningMode = true}">
        <!-- Lightning mode  - Code to display ui in Lightning mode -->
        this is Lightning mode
    </apex:outputpanel>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.