Salesforce Flow is amazing. It can do nearly all sort of things that we need in a very quick and simple way. As I develop more and more flows on a daily basis, I realize that the components on Flow Builder itself is not enough, hence in this post, I am going to share with you all on how to develop a more advanced Flow footer component to replace with the standard footer.

One thing I find it not that convenient is that we can only choose one option at a time when we navigate through the screen flow. We can either go to next screen by clicking the Next button in the screen footer, or go back to previous screen by clicking the Previous button. What if we want to navigate to another screen page other than the next screen page?

custom-flow-footer-buttons

3 custom Next buttons on the screen in this example (Withdraw, Modify, Winback)

First off, we need to create a lightning component that can be used directly in the flow screen. Here's the code for CustomFlowFooter.cmp component:

<!-- CustomFlowFooter.cmp -->
<aura:component implements="lightning:availableForFlowScreens" access="global">

    <aura:attribute name="nextButtonLabel1" type="String" default="Next"/>
    <aura:attribute name="nextButtonLabel2" type="String" default="Next"/>
    <aura:attribute name="nextButtonLabel3" type="String" default="Next"/>
    <aura:attribute name="nextButtonLabel4" type="String" default="Next"/>
    <aura:attribute name="nextButtonLabel5" type="String" default="Next"/>
    
    <aura:attribute name="nextButtonClass1" type="String" default="slds-button_brand"/>
    <aura:attribute name="nextButtonClass2" type="String" default="slds-button_brand"/>
    <aura:attribute name="nextButtonClass3" type="String" default="slds-button_brand"/>
    <aura:attribute name="nextButtonClass4" type="String" default="slds-button_brand"/>
    <aura:attribute name="nextButtonClass5" type="String" default="slds-button_brand"/>
    
    <aura:attribute name="showNextButton1" type="Boolean" default="false"/>
    <aura:attribute name="showNextButton2" type="Boolean" default="false"/>
    <aura:attribute name="showNextButton3" type="Boolean" default="false"/>
    <aura:attribute name="showNextButton4" type="Boolean" default="false"/>
    <aura:attribute name="showNextButton5" type="Boolean" default="false"/>
    
    <aura:attribute name="disableNextButton1" type="String" default="false"/>
    <aura:attribute name="disableNextButton2" type="String" default="false"/>
    <aura:attribute name="disableNextButton3" type="String" default="false"/>
    <aura:attribute name="disableNextButton4" type="String" default="false"/>
    <aura:attribute name="disableNextButton5" type="String" default="false"/>
    
    <aura:attribute name="disablePreviousButton" type="String" default="false"/>
    <aura:attribute name="previousButtonLabel" type="String" default = "Previous"/>
    <aura:attribute name="previousButtonClass" type="String" default="slds-button_neutral"/>
	<aura:attribute name="showPreviousButton" type="Boolean" default="false"/> 
    
    <aura:attribute name="buttonLocation" type="String" default="right"/>
    <aura:attribute name="buttonClick" type="String" default="" />
    <aura:attribute name="onFinalPage" type="Boolean" default="false"/>

    <footer class="slds-card__footer my-custom-footer slds-grid slds-grid_align-spread actionsBar" >
  
        <aura:if isTrue="{! v.buttonLocation == 'right' }">
            <div></div>
            <div></div>
        </aura:if>

        <aura:if isTrue="{! v.buttonLocation == 'middle' }">
            <div></div>
        </aura:if>
        
        <div>
            <aura:if isTrue="{! v.showPreviousButton }">
                <lightning:button disabled = "disablePreviousButton"
                                  class="{!'slds-button ' + v.previousButtonClass}" 
                                  label="{!v.previousButtonLabel}" 
                                  name="ButtonPrev" 
                                  onclick="{!c.handleClick}" />                   	
        	</aura:if>
            
            <aura:if isTrue="{! v.showNextButton1 }">
             	<lightning:button disabled = "{!v.disableNextButton1}"
                                  class="{!'slds-button ' + v.nextButtonClass1}" 
                                  label="{!v.nextButtonLabel1}" 
                                  name="ButtonNext1" 
                                  onclick="{!c.handleClick}" />                    	
        	</aura:if>            
       
            <aura:if isTrue="{! v.showNextButton2 }">
             	<lightning:button disabled = "{!v.disableNextButton2}"
                                  class="{!'slds-button ' + v.nextButtonClass2}" 
                                  label="{!v.nextButtonLabel2}" 
                                  name="ButtonNext2" 
                                  onclick="{!c.handleClick}" />                    	
        	</aura:if>         		 

            <aura:if isTrue="{! v.showNextButton3 }">
             	<lightning:button disabled = "{!v.disableNextButton3}"
                                  class="{!'slds-button ' + v.nextButtonClass3}" 
                                  label="{!v.nextButtonLabel3}" 
                                  name="ButtonNext3" 
                                  onclick="{!c.handleClick}" />                    	
        	</aura:if>  

            <aura:if isTrue="{! v.showNextButton4 }">
             	<lightning:button disabled = "{!v.disableNextButton4}"
                                  class="{!'slds-button ' + v.nextButtonClass4}" 
                                  label="{!v.nextButtonLabel4}" 
                                  name="ButtonNext4" 
                                  onclick="{!c.handleClick}" />                    	
        	</aura:if>  
            
            <aura:if isTrue="{! v.showNextButton5 }">
                <lightning:button disabled = "{!v.disableNextButton5}"
                                  class="{!'slds-button ' + v.nextButtonClass5}" 
                                  label="{!v.nextButtonLabel5}" 
                                  name="ButtonNext3" 
                                  onclick="{!c.handleClick}" />                    
        	</aura:if>  
            
        </div>
        
        <aura:if isTrue="{! v.buttonLocation == 'left' }">
            <div></div>
            <div></div>
        </aura:if>        

        <aura:if isTrue="{! v.buttonLocation == 'middle' }">
            <div></div>
        </aura:if>
        
    </footer>

</aura:component>

In CustomFlowFooter.cmp, we predefined all the buttons that we might need in the component with the variables from the flow. Next, we will need to hook up onClick handler to navigate through the flow:

// CustomFlowFooterController.js
({
	handleClick : function(component, event, helper) {
        
        var buttonName = event.getSource().get("v.name");
		var action ="";
   
        if (buttonName.includes('ButtonNext') ){
            if (component.get("v.onFinalPage") == true){
            	action="FINISH";
            } else{
                action="NEXT";
            }              
        } else{
            action="BACK";    
        }
 
        component.set("v.buttonClick", buttonName);
        console.log("action is: "+ action);

        var navigate = component.get('v.navigateFlow');  
        navigate(action); 
		
    }
})

In CustomFlowFooterController.js, you can set the buttonClick variable when a button is clicked. This is very important since we are going to rely on the buttonClick variable to know which button was clicked by the user.

Another thing that you might need to be aware of is to check whether you are on the final screen or not. If you are on the final screen, then you might need to set the onFinalPage variable to be true so that the next action is FINISH instead of NEXT. Otherwise, you might get flow error because of the navigating issue.

Feel free to customize the buttons or the components using CSS.

//  CustomFlowFooter.css
.THIS.my-custom-footer{
    margin-top: 1em !important;
    padding: 1em 0 !important;
}

Lastly, we need to create a design doc so that the flow can communicate with lightning component freely.

<!-- CustomFlowFooter.design -->
<design:component >
    <design:attribute name="nextButtonLabel1" label="Next Button Label 1" default="Next"/>
    <design:attribute name="nextButtonLabel2" label="Next Button Label 2" default="Next"/>
    <design:attribute name="nextButtonLabel3" label="Next Button Label 3" default="Next"/>
    <design:attribute name="nextButtonLabel4" label="Next Button Label 4" default="Next"/>
    <design:attribute name="nextButtonLabel5" label="Next Button Label 5" default="Next"/>

    <design:attribute name="nextButtonClass1" label="Next Button Class 1" default="slds-button_brand"/>
    <design:attribute name="nextButtonClass2" label="Next Button Class 2" default="slds-button_brand"/>
    <design:attribute name="nextButtonClass3" label="Next Button Class 3" default="slds-button_brand"/>
    <design:attribute name="nextButtonClass4" label="Next Button Class 4" default="slds-button_brand"/>
    <design:attribute name="nextButtonClass5" label="Next Button Class 5" default="slds-button_brand"/>
    
    <design:attribute name="showNextButton1" label="Show Next Button 1?" default="true"/>
    <design:attribute name="showNextButton2" label="Show Next Button 2?" default="false"/>
    <design:attribute name="showNextButton3" label="Show Next Button 3?" default="false"/>
    <design:attribute name="showNextButton4" label="Show Next Button 4?" default="false"/>
    <design:attribute name="showNextButton5" label="Show Next Button 5?" default="false"/>

    <design:attribute name="disableNextButton1" label="Disable Next Button 1?" default="false"/>
    <design:attribute name="disableNextButton2" label="Disable Next Button 2?" default="false"/>
    <design:attribute name="disableNextButton3" label="Disable Next Button 3?" default="false"/>
    <design:attribute name="disableNextButton4" label="Disable Next Button 4?" default="false"/>
    <design:attribute name="disableNextButton5" label="Disable Next Button 5?" default="false"/>
    
    <design:attribute name="previousButtonLabel" label="Previous Button Label" default="Previous"/>
    <design:attribute name="previousButtonClass" label="Previous Button Class" default="slds-button_neutral"/>
    <design:attribute name="showPreviousButton" label="Show Previous Button?" default="false"/>
    
    <design:attribute name="buttonLocation" label="Button Location? (left, middle, right)" default="right"/>
    <design:attribute name="buttonClick" label="Button Click (for output use only)" />
    <design:attribute name="onFinalPage" label="On Final Page?" default="false"/>

</design:component>

In CustomFlowFooter.design doc, I have included the following attributes so that those attributes can be passed into the CustomFlowFooter lightning component:

  • nextButtonLabelX - the next button's label name
  • nextButtonClassX - the css style for the next button (slds-button_brand, slds-button_neutral and etc.)
  • disableNextButtonX - determine whether the next button is disabled or not
  • previousButtonLabel - the previous button's label name
  • previousButtonClass - the css style for the previous button (slds-button_brand, slds-button_neutral and etc.)
  • disablePreviousButton - determine whether the previous button is disabled or not
  • buttonLocation - the location of the button group (left, middle, or right)
  • buttonClick - detect which button is clicked (for output use only)
  • onFinalPage - check whether the button is on the last page

Once we have created the lightning component, we can add it to the flow screen. You can specify how the buttons look like using the attributes on the right. For example, you can set a button as disabled, set the button style, or show multiple different buttons.

custom-flow-footer

Remember to set the Button Click output value to a variable like this:
custom-flow-footer-button-click

Based on the buttonClick variable value, we can set how the flow goes.
custom-flow-footer-statement

Oh, by the way, please remember to uncheck the Show Footer on the screen properties, otherwise you will be seeing both the custom and standard footer.

custom-flow-footer-show-footer


That's all about it! Very simple and fun, right? I hope you guys enjoy reading this post! See you all next time!

Post was published on , last updated on .

Like the content? Support the author by paypal.me!