A Flow Screen Component that plays sounds

Created by Yumi Ibrahimzade

ABOUT
This is a Lightning Component that plays a sound effect.
It can be used on Flow Screens and Lightning Pages.
In order to play a sound, you have to upload the sound file as a Static Resource and then enter the name of the file to the “Sound File” parameter.

INSTALLATION

PARAMETERS
Sound File – Enter the name of the sound file.

CONSIDERATIONS
This component loads the sound file from Static Resources and plays it. So it is recommended to use smaller file sizes, otherwise it might take some time to load the file.

HOW TO USE
1- Upload the sound file as a Static Resource.

2- Add “SoundCMP” to your Flow Screen.
3- Enter the name of the sound file to the parameter called “Sound File”.

Displaying Map with markers in Flow screen using Lightning Components by Terence Chiu

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. (edit: my other component works once I adjusted my clickjack settings)

SANDBOX
PRODUCTION

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'));
        params.push(component.get('v.otherParams'));
        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");
                urlEvent.setParams({
                     "url": vfURL
                });
                urlEvent.fire();

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) {
                    workspaceAPI.openSubtab({
                        parentTabId: parentTabId,
                        url: vfURL,
                        focus: true
                    }).then(function(openSubResponse) {
                        console.log("New SubTab Id: ", openSubResponse);
                    })
                    .catch(function(error) {
                        console.log(error);
                    });                        
                } else {
                    workspaceAPI.openTab({
                        url: vfURL,
                        focus: true
                    }).then(function(openParResponse) {
                        console.log("New ParentTab Id: ", openParResponse);
                    })
                    .catch(function(error) {
                        console.log(error);
                    });                        
                }

                // Because exiting the VF page will reopen the object record,
                // close the tab we started on
                if (tabResponse.closeable && !tabResponse.pinned) {
                    workspaceAPI.closeTab({
                        tabId: closeTabId
                    }).then(function(closeResponse) {
                        console.log("Closed: ", closeTitle);                      
                    })
                    .catch(function(error) {
                        console.log(error);
                    });                            
                } else {
                    console.log("Left Open: ", tabResponse.title);
                }
            })
            .catch(function(error) {
                console.log(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:card>
        <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" />
        </lightning:layoutItem>
    </lightning:card>

</aura:component>

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