Load a Visualforce Page with Parameters in Lightning

I was looking to display Visualforce pages using the RecordId inside of my Lightning Record pages. After finding a very elegant solution to pass the RecordId from a Lightning Component container to a Visualforce page displayed in an iframe I decided it was time to move the solution from the Sandbox into Production.

What worked perfectly in the Sandbox gave me nothing but a blank component in Production. After spending way too much time trying to find a solution, I gave up and went to Plan B.


Plan B

I was able to use a Lightning Component to navigate to a URL, so I built a component to build the URL for the Visualforce page including the parameter for the RecordId of the page.

    doInit : function(component, event, helper) {
        var params = new Array();
        params.push(component.get('v.recordIdVar') + '=' + component.get('v.recordId'));
        component.set('v.queryString', params.join('&'))

    openPage : function(component, event, helper) {

        // Show spinner once button is pressed
        var spinner = component.find('spinner');
        $A.util.removeClass(spinner, 'slds-hide');

        // Build url for Visualforce page
        var vfURL = 'https://' + component.get("v.domain") + '--c.visualforce.com/apex/';
        vfURL = vfURL + component.get("v.pageName") + '?';
        vfURL = vfURL + component.get("v.queryString");
        console.log("VF URL: ",vfURL);

On a standard Lightning page, the component switches from the Record page to the Visualforce page, returning to the Record page when the Visualforce page exits.

                // Handle non-console user
                console.log("Not in Console");
                var urlEvent = $A.get("e.force:navigateToURL");
                     "url": vfURL

It is a bit different on a Console page where the Visualforce Page is loaded in a new Tab which reverts to the Record page Tab when exiting. This normally leaves a second “dead” Record page Tab behind so I made sure the component saved the ID of the Calling Tab or Subtab and closed the “dead” tab when finishing with the Visualforce page.

// Check to see if running in a Console
    var workspaceAPI = component.find("workspace");
    workspaceAPI.isConsoleNavigation().then(function(consoleResponse) {            
        console.log("IsConsole: ", consoleResponse);
        if (consoleResponse) {

            // Save current tab info
            workspaceAPI.getFocusedTabInfo().then(function(tabResponse) {
                var closeTabId = tabResponse.tabId;
                var closeTitle = tabResponse.title;
                var parentTabId = tabResponse.parentTabId;
                var isSubtab = tabResponse.isSubtab;
                console.log("Current Tab: ", closeTabId + " | " + closeTitle);
                console.log("Is Sub: ",isSubtab," ParentId: ",parentTabId);

                // Open Visualforce Page in a new tab
                if (isSubtab) {
                        parentTabId: parentTabId,
                        url: vfURL,
                        focus: true
                    }).then(function(openSubResponse) {
                        console.log("New SubTab Id: ", openSubResponse);
                    .catch(function(error) {
                } else {
                        url: vfURL,
                        focus: true
                    }).then(function(openParResponse) {
                        console.log("New ParentTab Id: ", openParResponse);
                    .catch(function(error) {

                // Because exiting the VF page will reopen the object record,
                // close the tab we started on
                if (tabResponse.closeable && !tabResponse.pinned) {
                        tabId: closeTabId
                    }).then(function(closeResponse) {
                        console.log("Closed: ", closeTitle);                      
                    .catch(function(error) {
                } else {
                    console.log("Left Open: ", tabResponse.title);
            .catch(function(error) {

Rather than load the Visualforce page immediately, I display a button. On the button press, the component loads the Visualforce page.

<aura:component implements="flexipage:availableForAllPageTypes,force:hasRecordId" access="global">

    <lightning:workspaceAPI aura:id="workspace" />

    <aura:attribute name="buttonLabel" type="String" />
    <aura:attribute name="buttonVariant" type="String" default="neutral" />
    <aura:attribute name="domain" type="String" />
    <aura:attribute name="pageName" type="String" />
    <aura:attribute name="recordIdVar" type="String" />
    <aura:attribute name="otherParams" type="String" />

    <aura:attribute name="queryString" type="String" />

    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />

        <lightning:layoutItem padding="around-small">
            <lightning:button label="{!v.buttonLabel}" variant="{!v.buttonVariant}" onclick="{!c.openPage}" />
            <lightning:spinner aura:id="spinner" alternativeText="Loading" variant="brand" size="large" class="slds-hide" />


I’ve made the component as generic as possible by providing the following attributes one can use when placing the component on their Lightning Record page.

  • Button Label (Text to appear on the Button)
  • Button Variant (Button styling: base, neutral, brand, destructive, success)
  • Domain Name (Your Production or Sandbox domain name)
  • Visualforce Page Name (The API Name of the Visualforce Page)
  • RecordId Parameter Name (The name of the URL parameter for the RecordId)
  • Additional URL Parameters (Any other URL parameters & values)

Here’s the Component in Action

Find More at Unofficial SF

Visit Unofficial SF (Load Visualforce Page) to get the source code for this component and some of my other Lightning Components, Visual Flow Screen Components, Visual Flow Actions and much more.

Some of my Other Lightning Page Components

Close Console Tabs

Winter ’19 now allows you to close all non-pinned Lightning Console tabs (Shift-W). You can install this component to provide a Utility Bar option to close all your opened tabs and even specify whether or not to include pinned tabs.

Field Update Button

This is a generic Lightning Component that can be used in place of a JavaScript button to set the value of a single field in a record. This is handy for using a button to trigger a Process Builder.

Large Text Area Component

This is a generic Lightning Component that allows for the display or editing of a Long Text Area field on the record page with a larger input box than what is standard and the ability to toggle it on and off.

Quick Action Button

This is a generic Lightning Component that allows a Button to execute a Quick Action. The Button can be placed anywhere on a Lightning Record Page.

Toggle Field Button

This is a generic Lightning Component that allows a Toggle Button to set/clear a checkbox field. The Button can be placed anywhere on a Lightning Record Page.

Some Flow Screen Components I’ve Enhanced

The Navigation Button component has been updated to support dual buttons.  Think OK/Cancel or Previous/Next. Navigation Button

Now you can create interactive images and 3D buttons – Image Button

Filters, Parent/Child and more for the flow screen Lookup component.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s