Lightning Flow iFrame Javascript Widget

Javascript Widget

This widget utilizes the great cross-domain iframe resizer from David J. Bradshaw.

Features

  • Dynamic iFrame height adjustment: responsive to Flow content and parent window responsive width
  • Pass all query strings parent page to the iFrame 
  • Set manual querystring values in shortcode 
  • Finish URL for redirect on flow complete

Implementation Options

For folks running WordPress, I have a plugin available in the directory.

Folks looking to implement on any other site can use the pure javascript implementation

Variable Options

AttributeDescriptionAllowed ValuesRequiredDefault
iframeurlurl of the public visualforce page rendering the flowfull urltrue“https://threelevers.secure.force.com/demo/iFrameDemo”
endurlurl to redirect folks to upon completing the flowfull urlfalsenone
heightinitial height of the iframe in pixels before fully loadednumber of pixels (i.e. “75px”)false“50px”
extraqsany querystring you want to pass to the iframe, in addition to the querystrings on the parent page. key/value pair separated by “=”. pairs separated “&” (example “foo=bar&this=that”)falsenone
easeset if the height adjustment of the iframe is eased“true” or “false”false“false”
easespeedspeed of the ease in secondsany number (example “.5” or “2”)false“.2”
lazydesignate ‘loading=”lazy”‘ to iframe“true” or “false”false“true”

Demo

The code block used to embed the demo flow: Test passing parameters via querystring by going to: https://threelevers.com/plugins/iframe-embed/?count=7
				
					<!-- Salesforce Flow widget begins -->
<!-- Update the variables below per your requirements. See instructions at https://threelevers.com/plugins/iframe-embed/js -->
<script>
const ifc={
    //url for Flow on Visualforce Page - **MANDATORY** 
	'iframeurl' : 'https://threelevers.secure.force.com/demo/iFrameDemo', 
	//url to direct users upon Flow finish
    'endurl' : 'https://threelevers.com/plugins/iframe-embed/iframe-finish-demo/',
	//initial height of iframe, will be updated as soon as Flow loads
	'height' : '65', 
	//any parameters you want to pass to the Visualforce Page, querystrings will also be pass from the parent page to the iFrame
	'extraqs' : 'count=13',
	//do you want the iframe to ease it's height adjustment
	'ease' : 'true', 
	//spead of the ease if set to true
	'easespeed' : '.5', 
	//do you want the iFrame to be set to LazyLoad
	'lazy' : 'true' 
}
</script>
<!-- DO NOT EDIT BELOW THIS LINE -->
<div id="tliframewrap"></div>
<script src="https://cdn.jsdelivr.net/wp/plugins/lightning-flow-iframe/tags/1.0.0/js/lighningiFrame.js" type="text/javascript"></script>
<!-- Salesforce Flow widget ends -->
				
			
				
					<apex:page id="iFrame-Demo" showHeader="false" docType="html-5.0" lightningStyleSheets="true" sidebar="false" standardStylesheets="false">
    <html>

    <head>
        <apex:includeLightning />
        <meta content="width=device-width, initial-scale=1.0" name="viewport" />
        <style>
            body {
                background: #efefef !important;
                color: #333;
            }
        </style>
        <script type='text/javascript' src='https://threelevers.com/wp-content/plugins/lightning-flow-iframe/js/iframeResizer.contentWindow.min.js' id='iframe-resizer'></script>
    </head>

    <body class="slds-scope">
            <div id="flowContainer" >
                <div id="Spinner" class="demo-only demo-only_viewport" style="height:6rem;position:relative">
                    <div role="status" class="slds-spinner slds-spinner_medium">
                        <span class="slds-assistive-text">Loading</span>
                        <div class="slds-spinner__dot-a"></div>
                        <div class="slds-spinner__dot-b"></div>
                    </div>
                </div>
            </div>
            <script>
                var statusChange = function(event) {
                    if (event.getParam("status") === "FINISHED") {
                        // Control what happens when the interview finishes
                        var url = "{!$CurrentPage.parameters.endUrl}"; //capture value entered in shortcode

                        //check if any value was given for endurl
                        if (url.length > 1) {
                            window.parent.location.href = url; //redirect to endUrl
                        }
                        var outputVariables = event.getParam("outputVariables");
                        var key;
                        for (key in outputVariables) {
                            if (outputVariables[key].name === "myOutput") {
                                // Do something with an output variable
                            }
                        }
                    }
                };
                $Lightning.use("c:FlowOutApp", function() {
                    // Create the flow component and set the onstatuschange attribute
                    $Lightning.createComponent("lightning:flow", {
                            "onstatuschange": statusChange
                        },
                        "flowContainer",
                        function(component) {
                            // Set the input variables
                            var inputVariables = [{
                                name: 'inputDivCount',
                                type: 'String',
                                value: '{!$CurrentPage.parameters.count}'
                            }];
                            ///////////
                            let height;
                            var checkExist = setInterval(function() {
                                height = document.body.scrollHeight;
                                window.parent.postMessage({
                                    frameHeight: height
                                }, '*');
                                console.log(height);
                            }, 500); // check every 500ms
                            ///////////
                            document.getElementById('Spinner').hidden = true;
                            // Start an interview in the flowContainer div, and 
                            // initializes the input variables.
                            component.startFlow("Expanding_Flow", inputVariables);

                        }
                    );
                });
            </script>

    </body>

    </html>
</apex:page>
				
			

See external example on https://jsfiddle.net/jasonbest/e7r3618v

Instructions

  1. Prepare Lighting Flow on Visualforce page
  2. Make Visualforce Public
  3. Add code block to your page

1. Prepare Lightning Flow on Visualforce page

Follow the example from Salesforce to render the flow on a Visualforce page.

Next, you will need to add some lines of code to the Visualforce page to allow it it communicate with the parent page on which you will iframe it.

Add the javascript file right before the closing </head> tag. Be sure to update domain name to your domain. 

				
					 <script type='text/javascript' src='https://DOMAINNAME/wp-content/plugins/lightning-flow-iframe/js/iframeResizer.contentWindow.min.js' id='iframe-resizer'></script>

				
			

Modify FINISHED behavior to redirect to url set in the shortcode.

				
					if (event.getParam("status") === "FINISHED") {
    // Control what happens when the interview finishes
    var url = "{!$CurrentPage.parameters.endUrl}"; //capture value entered in shortcode

    //check if any value was given for endurl
    if (url.length > 1) {
        window.parent.location.href = url; //redirect to endUrl
    }
				
			

Optional
If you need to pass input variables to the flow, modify your inputVariables collection to reflect the variable names you will use. See the following example:

				
					// Set the input variables
var inputVariables = [{
    name: 'inputName1', //named Flow input variable
    type: 'String', //variable data type
    value: '{!$CurrentPage.parameters.qsname}' //name of the querystring you will use to popuate the variable 
}];
				
			

Just above component.startFlow("myFlowName", inputVariables); add line 1-9 of the following code.

				
					let height;
var checkExist = setInterval(function() {
    height = document.body.scrollHeight;
    window.parent.postMessage({
        frameHeight: height
    }, '*');
    console.log(height);
}, 500); // check every 500ms
///////////
// Start an interview in the flowContainer div, and 
// initializes the input variables.
component.startFlow("myFlowName", inputVariables);
				
			

2. Make Visualforce Page Public

Refer to the following documentation to create a Salesforce site with the proper configuration

3. Add Code Block to page

Add shortcode to your page. Follow the Shortcode Format and Options

Feedback and Support

Support for the WordPress plugin is available here.

 

If you need support for the javascript implementation, please complete the form below and I will get back to you when I am able.