Last week I was exploring the options to show a context sensitive pop-up in record detail pages. The pop-up needed to use the sObject name of the record that was being visualised in the detail page. I wanted this functionality to be available in classic and Lightning Experience. So I spent some time exploring the options that we have to do this. Are Lightning Components ready to fulfil my requirements?
These are the options I explored:
A) LEX: Create a Lightning Component with the info I want to show in the pop-up and embed it in a Lightning Action: on Winter 17 Salesforce released Lightning Actions. My first thought was that these actions could show my problem in a quick and elegant way. What I did to test it:
- I created a Lightning Component that implements force:lightningQuickAction and force:hasSObjectName, that was supposed to be the pop-up I wanted to show on each record detail page. I referenced {!v.sObjectName} in the Component, to get in which sObject type page the Component is being rendered.
<aura:component implements="force:lightningQuickAction,force:hasSObjectName"> <ui:outputText value="{!v.sObjectName}" /> </aura:component>
- I created a Lightning Action on an sObject (eg: Account). Bear in mind I could have created a global action as well.
- I modified the sObject Layout to show this Lightning Action on “Salesforce1 and Lightning Experience Actions” menu.
The conclusions are that:
- force:hasSObjectName worked fine and I was able to see in which sObject’s detail page the pop-up was being shown
- The Component can be reused in any detail page
- The Component can be shown in a popup, which was one of my requirements, in a pretty straightforward way
- Sadly, Lightning Actions don’t work in classic
B) LEX: Create a Lightning Component with the info I want to show in the pop-up and show it on Utility Bar
- In this case, we would need to create a Lightning Component that implements flexipage:availableForAllPageTypes
- Then create a Lightning App in which we configure the Utility bar to show the Component.
With this approach:
- Utility bar can be shown in any page and it is easily accessible
- Utility bar will show something similar to a pop-up
- force:hasSObjectName won’t work, and we don’t have an easy way of detecting in which page it is being rendered
- Utility bar would be monopolized by this Component
- Again, the solution works in Lightning Experience but not in Classic
C) LEX: Create a Lightning Component that shows the record details with force:recordView, and implement a Javascript like pop-up there. Overwrite the view standard action to show the Component.
Here you have an example of how to do this. In this case:
- force:hasSObjectName will work fine
- We can show a real pop-up
- The component would be reusable for any sObject
- Not valid if users are using customised record detail pages in Lightning Experience
- Again, the solution works in Lightning Experience but not in Classic
D) LEX: Create a Lightning Component with the info I want to show in the pop-up, and a button to show / hide it. Add the Lightning Component to a section on record detail pages for Lightning Experience (with App Builder).
We would have to add a mechanism to show / hide the pop-up content. You can check here how to do this in detail, it is pretty straightforward.
The conclusions are:
- force:hasSObjectName works fine
- As the Component is being rendered in a section, we can’t really show a pop-up that overlays the page, we can only hide / show something dynamically in the Component space.
- The solution works in Lightning Experience but not in classic
E) LEX: Create a Lightning Component with the info I want to show in the pop-up. Show / Hide the Component on button click on a Visualforce page (Lightning Out). Add the Visualforce page to a section on record detail pages for Lightning Experience (with App Builder).
- This time I created a Lightning Component similar to the one created in solution A), but without implementing the force:lightningQuickAction interface, as I was not going to use a Lightning Action. I tried using force:sObjectName interface, but it does not work when using Lightning Out, so I had to pass a parameter from the Visualforce page to detect the sObject name.
<aura:component> <aura:attribute name="sObjectNameFromVF" type="String" /> <ui:outputText value="{!v.sObjectNameFromVF}" /> </aura:component>
- Then I created a Lightning Standalone App that implements ltng:outApp and has a dependency with the Component.
<aura:application extends="ltng:outApp" > <aura:dependency resource="c:PopUp"/> </aura:application>
- I created a Visualforce page associated with an sObject (eg: Account). The page creates the Lightning Standalone App dynamically with Lightning Out, and initializes the Component, passing in the sObject name, on a button click.
<apex:page standardController="Account"> <apex:includeLightning /> <button type="button" onclick="displayPopup()">Show Popup</button> <div id="lightning" style="display:none;width:340px;margin:0 auto;background-color: rgba(0,0,0,0.2);"/> <script> function displayPopup() { $Lightning.use("c:PopUpApp", function() { $Lightning.createComponent("c:PopUP", {sObjectNameFromVF: "Account"}, "lightning", function(cmp) { document.getElementById("lightning").style.display = "block"; }); }); } </script> </apex:page>
- I set the page as “Available for Salesforce mobile apps and Lightning Pages”
- I configured the Account detail page on App Builder to show the Visualforce page
This is the result I obtained in Lightning Experience:
(Don’t take into account the ugly pop-up I have created, please! :))
The conclusions in this case are those that we got with solution D), but:
- This time the Visualforce page will be reusable in classic (continue reading and you will find out).
- force:hasSObjectName won’t work, but we can pass the sObject name from the Visualforce page
- We would need a Visualforce page for each detail page in which we want to show the pop-up as we need to specify its standard controller in order we can embed it in the standard layout
- As the page is being rendered in a section, we can’t really show a pop-up that overlays the page, we can only hide / show a section dynamically in the section space.
F) CLASSIC: Create a Lightning Component with the info I want to show in the pop-up. Show / Hide the Component on button click on a Visualforce page (Lightning Out). Add the Visualforce page to a section on record standard layout.
In this case, I followed the same steps than in solution E), but I embedded the Visualforce page on a section on Account standard layout.
This is the result I obtained in Classic:
The conclusions are the same than those in solution E).
G) CLASSIC: Create a Lightning Component with the info I want to show in the pop-up. Show / Hide the Component on button click on a Visualforce page (Lightning Out). Use in the page, and overwrite record view standard action.
Steps 1 and 2 are equal to those in solution E) or F).
- Step 3 would vary a bit. This time, we would embed the apex:detail tag in the Visualforce page. This tag will show the standard layout as configured by the user inside your Visualforce page.
<apex:page standardController="Account"> <apex:includeLightning /> <button type="button" onclick="displayPopup()">Show Popup</button> <div id="lightning" style="display:none;width:340px;position:absolute;top:20%;left:40%;background-color: black; color:white;"/> <apex:detail /> <script> function displayPopup() { $Lightning.use("c:PopUpApp", function() { $Lightning.createComponent("c:PopUP", {sObjectNameFromVF: "Account"}, "lightning", function(cmp) { document.getElementById("lightning").style.display = "block"; }); }); } </script> </apex:page>
Note that I have modified the pop-up styling to have an absolute position. Now I can do this, because that bit is not inside an iframe anymore.
- Then we would need to override the record view button to redirect to our Visualforce page.
The result of seeing this in Classic is the next one:
However if I show it in Lightning Experience, the apex:detail tag is not styled pretty:
The conclusions in this case are:
- force:hasSObjectName won’t work, but we can pass the sObject name from the Visualforce page
- We can show a real pop-up
- We would need a Visualforce page for each detail page in which we want to show the pop-up as we need to specify its standard controller in order we can embed it in the standard layout
- The Visualforce page is reusable in Classic and Lightning Experience, but in Lightning Experience it looks ugly
General Conclusions:
Solutions E) and F) (really the same one) is valid for Lightning Experience and Classic, however they don’t fit well our requirement of showing a pop-up. That good be a good solution for other use cases, as showing a something in a section.
Solution G) is valid for Lightning Experience and Classic, but looks ugly in Lightning Experience. And as far as I know, it is not in Salesforce roadmap to make apex:detail tag look fine in LEX.
So, in my opinion, what is the best we can do?
- Embed the Component in a Lightning Action as we did in Solution A) for Lightning Experience, as they will show you a real context-sensitive pop-up with a minimal effort.
- Implement Solution G) (apex:detail) for Classic
The good news is that these two configurations are compatible!
I will write a post soon with the options that we have to do the same on a list view.
Awesome!
LikeLiked by 1 person
This is the next level in depth POC of Lightning Component and Custom Button. Keep it up.
LikeLike