Introduction
In this article we will see how to create Flows and reusable Lightning components to simulate the standard Path behavior.
The Standard Lightning Path is a standard component usable in Lighting record pages of most Salesforce standard Object and all custom objects.
Unfortunately, this component has some limitations that our solution can answer to:
- It cannot be used for the Case Object on Communities.
- The Path is dependent to a picklist field of the chosen object.
- It can display maximum five fields per step.
Figure 1: Custom Path final result.
Audience.
This article describes steps to creates Lightning components.
A developer background is helpful to understand the mechanics but not needed to reproduce the below steps.
Knowledge on how to create (visual) Flows however is needed since this article does not offer an in-depth description of the process and only focuses on the relevant aspects.
Building alternative path Lightning components.
Figure 2: Page composition.
We will build two separate Lightning components to achieve this result.
One component to display the Progress Indicator bar (Path equivalent) and one component to display our Flow.
This separation gives us more options when designing our Lightning record page layout and Communities page layouts since the components can be placed separately on the page.
To communicate through the Lightning record page, our components will use events:
Figure 3: Components communication.
Progress Indicator lightning component.
There are several base Lightning components usable to recreate the Salesforce standard Path visuals and behavior:
- lightning:Path
- lightning:picklistPath
- lightning:progressIndicator
We will use the lightning:progressIndicator since it’s specifically designed to work with Flows (even though it’s not mandatory).
Notes: Among the custom solutions, lightning:Path is the closest to the standard Salesforce path behavior but it’s not working properly on Communities at the moment.
Let’s start:
– First, we head to the developer console:
Figure 5: Enter developer console.
– From there we create our first Lightning component: File > New > Lighting Component
Figure 6: Creating CustomPath lightning component.
– Replace the existing code with the following one:
Don’t try to save yet, you would get an error. That’s because the markup references a component that does not exist yet (L19), we will handle that later.
1. <aura:component implements="forceCommunity:availableForAllPageTypes,
2. flexipage:availableForAllPageTypes,
3. flexipage:availableForRecordHome,
4. force:hasRecordId"
5. access="global">
6.
7.
8. <!-- ATTRIBUTES -->
9. <aura:attribute name="currentStage"
10. type="Object"
11. description="Will contains the current stage of the flow."/>
12.
13. <aura:attribute name="activeStages"
14. type="Object[]"
15. description="Will contains all the active stage of the flow. We contruct our path based on this list"/>
16.
17. <!-- HANDLERS -->
18. <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
19. <aura:handler event="c:statusChanged" action="{!c.handleStatusChanged}"/>
20.
21. <!-- MARKUP -->
22. <br></br>
23. <lightning:progressIndicator aura:id="progressIndicator"
24. currentStep="{!v.currentStage.name}"
25. type="path"
26. variant="base"
27. />
28.
29. </aura:component>
Notes:
The Component implements the forceCommunity:availableForAllPageTypes interface that makes it available for Communities’ pages.
– We add a JavaScript controller to our component. To do that we click on the CONTROLLER button on the right side of the screen.
Figure 7: Creating CustomPath controller.
– Replace the existing code with the following one:
1. ({
2.
3. //Launched at component initialization.
4. doInit : function(component, event, helper) {
5.
6. //Call helper to create/Update the Porgression indicator bar
7. helper.initPath(component, event, helper);
8.
9. },
10.
11. /*
12. * Launched when StatusChanged event is received.
13. * Updates the Porgression indicator bar based on new information recieved from the event.
14. */
15. handleStatusChanged : function(component, event, helper){
16.
17. //getting currentStage and activeStages parameters from the "StatusChanged" event and
18. //updating the currentStage and activeStages attributes in the markup.
19. component.set("v.currentStage", event.getParam("currentStage"));
20. component.set("v.activeStages", event.getParam("activeStages"));
21.
22. //Call helper to create/Update the Porgression indicator bar
23. helper.initPath(component, event, helper);
24.
25.
26. }
27.
28. })
– Save (ctrl + s).
– We add a JavaScript helper to our component the same way we did with the controller but this time selecting the HELPER button.
– Replace the existing code with the following one:
1. ({
2.
3. /*
4. * Function that will dynamically construct the path (progressIndicator) bar based on the value of the "activeStages" attribute.
5. */
6. initPath : function(component, event, helper) {
7.
8. var progressIndicator = component.find('progressIndicator');
9. var body = [];
10.
11. var activeStages = component.get("v.activeStages");
12.
13. //for each value in the activeStages list, we create a new element of "lightning:progressStep" and
14. //we add it to the progressIndicator component to costruct our path.
15. var stage;
16. for (var key in activeStages) {
17.
18. stage = activeStages[key];
19.
20. $A.createComponent(
21. "lightning:progressStep",
22. {
23. "aura:id": "step_" + stage.name,
24. "label": stage.label,
25. "value": stage.name
26. },
27. function(newProgressStep, status, errorMessage){
28. // Add the new step to the progress array
29. if (status === "SUCCESS") {
30. body.push(newProgressStep);
31. progressIndicator.set("v.body", body);
32. }
33.
34. //Handle error cases here.
35. }
36. );
37. }
38.
39. }
40. })
– Save (ctrl + s).
Now, remember that we could not save our component markup during the first step ?
Our component markup was referencing (Ligne 19) an event that we have not yet created.
This event will allow our component to communicate with other components in the page.
Let’s create it now: File > New > Lightning Event
Figure 8:Creating StatusChanged event.
– Replace the existing code with the following one:
1. <aura:event type="APPLICATION">
2. <aura:attribute name="currentStage" type="Object"/>
3. <aura:attribute name="activeStages" type="Object[]"/>
4. </aura:event>
– Save (ctrl + s).
– Head back to the markup (customPath.cmp tab) and save (ctrl + s).
And that’s it for the Custom Path component.
It can already be added to the lightning record page of any object but will not display anything for the moment.
Flow embedded lightning component.
Figure 9: Custom flow lightning component.
The Flow component will embed a Flow and will be able to send information about the Flow to other components in the page (for instance to the Progression indicator we created earlier).
Let’s start:
– In the developer console, we create the customFlow lightning component:
Figure 10: Creating CustomFlow lightning component.
– Replace the existing code with the following one:
1. <aura:component implements="flexipage:availableForRecordHome,
2. force:hasRecordId,
3. forceCommunity:availableForAllPageTypes"
4. access="global" >
5.
6. <!-- ATTRIBUTES -->
7.
8. <aura:attribute name="flowName"
9. type="String"
10. description="ApiName of the flow."/>
11.
12. <aura:attribute name="currentStage"
13. type="Object"
14. description="Will contains the current stage of the flow."/>
15.
16. <aura:attribute name="activeStages"
17. type="Object[]"
18. description="Will contains all the active stage of the flow. We contruct our path based on this list"/>
19.
20. <!-- HANDLERS -->
21. <aura:handler name="init" value="{!this}" action="{!c.init}" />
22.
23. <!-- EVENTS -->
24. <aura:registerEvent name="statusChanged" type="c:statusChanged"/>
25.
26. <!-- MARKUP -->
27. <article class="slds-card">
28.
29. <lightning:flow aura:id="caseFlow"
30. onstatuschange="{!c.handleStatusChange}"/>
31. </article>
32. </aura:component>
– We add a JavaScript controller to our component.
– Replace the existing code with the following one:
1. ({
2. //Start the defined flow.
3. init : function (component) {
4.
5. var flowName = component.get("v.flowName");
6.
7. if(flowName){
8.
9. //caseFlow: is the identifier of the flow component in the markup (the view).
10. var flow = component.find("caseFlow");
11. var flowName = component.get("v.flowName");
12. flow.startFlow(flowName);
13.
14. }
15. },
16.
17.
18. /*
19. * Handle status change of the flow (user click on next, finish etc...).
20. * Send an event that boradcast the current stage and the active stages of the flow
21. * to the other lightning component of the page.
22. */
23. handleStatusChange : function (component, event) {
24.
25. var flowName = component.get("v.flowName");
26.
27. if(flowName){
28.
29. // Pass $Flow.ActiveStages into the activeStages attribute
30. // and $Flow.CurrentStage into the currentStage attribute
31. component.set("v.currentStage", event.getParam("currentStage"));
32. component.set("v.activeStages", event.getParam("activeStages"));
33.
34. var currentStage = component.get("v.currentStage");
35. var activeStages = component.get("v.activeStages");
36.
37. //Fire the statusChanged to transmit the "currentStage" and "activeStages" attributes to the other components.
38. var statusChanged = $A.get("e.c:statusChanged");
39. statusChanged.setParams({
40. "currentStage" : currentStage,
41. "activeStages" : activeStages
42. });
43. statusChanged.fire();
44.
45. }
46.
47.
48.
49.
50. },
51. })
Now we want to create a design resources for our customFlow lightning component.
This will allow administrators to specify which flow they want to embed in the component.
This will be configurable in the lightning app builder or the community builder.
– We click on the DESIGN button on the rigth:
Figure 11: CustomFlow design ressource.
– Replace the existing code with the following one:
1. <design:component>
2. <design:attribute name="flowName" label="Flow Name" description="ApiName of the flow we want to display." />
3. </design:component>
Both components are now built and can be used in Lightning record page as well as community detail pages.
Don’t forget to set the Flow Api name in the CustomFlow lightning component parameters of the Lightning app builder (or community appbuilder) to define which flow should be used:
Figure 12:Setup flow api name in Lightning app Builder.
Building Case sample flow.
To test our component, we need an existing flow.
We will not describe step by step how to create a flow here but focus on the definition of the flow stages that will be used later in our Progression Indicator component.
Here is what will look like our reference flow:
Figure 13: Sample flow process.
This sample flow handles the Case record process from its creation to its closure.
Our Case has four status:
- New = > has just been created (New stage).
- Pending => Is waiting for customer answer (Need more information stage).
- Working => Is processed by Customer support agents (Being processed stage).
- Closed => Is closed (Closed stage).
Our flow will also have four stages to mirror the Case status but know that the Case status and the flow stages can be independent to one another.
To create the four stages of our Flow that will later compose the Progression Indicator bar at the top of our Case lightning record page we proceed as follow:
– In the flow designer we go to the Resources tab and double click Stage.
Figure 14: Creating flow stages.
– Then we create the first stage as follow:
Label: New
Unique name: NewStage
Order: 10
Acive by Default: true
Figure 15: Define flow first stage.
– We create the other stages as follow:
Label | Unique name | Order | Acive by Default |
Need more information | NeedMoreInformationStage | 20 | true |
Being processed | BeingProcessedStage | 30 | true |
Closed | ClosedStage | 40 | true |
You can see the created stage in the Explorer tab:
Figure 16: Visualize flow stages.
Bibliography
Training sources:
- Lightning component Library: https://developer.salesforce.com/docs/component-library/overview/components
- Lightning Progress Indicator info: https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/components_using_flow_stages_wrapper.htm
- Lightning Path info: https://developer.salesforce.com/blogs/2018/06/using-path-in-your-custom-lightning-component.html
Tools:
- To copy paste formatted code samples to word documents: http://www.planetb.ca/syntax-highlight-word
- To remove number from code copied from this document : http://remove-line-numbers.ruurtjan.com/