To refer the most efficient way to navigate from one component to another, please refer the below post which has been updated in the Winter’17 release.
The technique mentioned in the above post is still in Beta mode, so you may continue to use the below approach until Salesforce generally announces it’s availability.
In my last post, I had briefed about Salesforce lightning events and its workflow. We will now walk through a scenario wherein we implement a functionality of lightning events.
We build a lot of components when it comes to building a Salesforce lightning application. So, how do we bridge all of these components together ? Lightning events are the righteous way to achieve this.
Let’s assume a scenario wherein there are two components in which one component accepts two user inputs and adds the two values and there is another component which would simply display the added value. So, how will the component1 pass on the result to component2 ? Well, we define a lightning event for this scenario and allow component1 to fire the event, which can be caught by the event handlers of component2.
So, Let’s define a lightning event named as “NavigateToC2”. Since, the component1 will have a value to be passed on to component2, the event will also need to have an attribute associated with it. So the event snippet should look something like this.
NavigateToC2.evt
<aura:event type="APPLICATION"> <aura:attribute name="result" type="String"/> </aura:event>
We will now define the Component1 which would accept two input values from user and sum it. The code snippet for Component1 is pasted below
Component1.cmp
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes"> <aura:attribute name="Result" type="String"/> <aura:registerEvent name="navigate" type="c:NavigateToC2"/> <ui:inputText aura:id="n1" maxlength="5" size="5" label="Number1" required="true"/> <ui:inputText aura:id="n2" maxlength="5" size="5" label="Number2" required="true"/> <ui:button label="Sum" press="{!c.Calculate}"/> </aura:component>
If you look at the above component, you will see that this component has registered the event “NavigateToC2” using the <aura:registerEvent> tag. This is a declaration that the component states to notify that it will fire the “NavigateToC2” at some point in time.
The controller for Component1.cmp is pasted below
Component1Controller.js
({ Calculate : function(component, event, helper) { var a = component.find("n1").get("v.value"); var b = component.find("n2").get("v.value"); var res = parseInt(a) + parseInt(b); res = res + ''; var evt = $A.get("e.c:NavigateToC2"); evt.setParams({ "result": res}); evt.fire(); } })
In the above controller of Component1, we are capturing the user inputs, converting it to integer data type, adding the two values and again converting it back to String data type. The final result is then passed to the “NavigateToC2” event and fired.
Now, we need to define the Component2, which will display the result. Below is the snippet of Component2.
Component2.cmp
<aura:component > <aura:attribute name="res" type="String" /> The result is {!v.res} </aura:component>
The above component is pretty straightforward.
So, now that both the components and events are defined, how do we bundle them all together?
We will need a parent component to bring all the components and event under one umbrella. So, let’s name the parent component as “MainComp”. This component will basically be rendering the different components at different point in time.
Below is the snippet of MainComp.cmp
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes"> <aura:handler name="init" value="{!this}" action="{!c.doInit}"/> <aura:handler event="c:NavigateToC2" action="{!c.NavigateComponent}"/> {!v.body} </aura:component>
In the above component you will notice that I have incorporated the event handler for handling the event that will be fired by Component1. I didn’t incorporate this event handler in Component2 is because it is the MainComp.cmp that will render all the components. So putting the event handler in the Component which will render the other Components definitely makes sense.
The controller for the MainComp.cmp is pasted below
MainCompController.js
({ doInit : function(component, event, helper) { $A.createComponent( "c:Component1", { }, function(newCmp){ if (component.isValid()) { component.set("v.body", newCmp); } } ); }, NavigateComponent : function(component,event,helper) { $A.createComponent( "c:Component2", { "res" : event.getParam("result") }, function(newCmp){ if (component.isValid()) { component.set("v.body", newCmp); } } ); } })
So, I will brief you about the functionality of MainComp.cmp. This component has two handlers viz; the “init” handler and “NavigateToC2” handler. The “init” handler is trigger when the component loads. This will invoke the “doInit” method and it will call the “createComponent” method, to which the Component1 is passed as an input parameter. Thus MainComp.cmp will render the Component1 during the initial loading.
So, what happens when the “NavigateToC2” event is fired by Component1. At this point, since the MainComp.cmp has declared the event handler for “NavigateToC2”, it will catch the event fired by Component1 along with the parameter passed to the event. The event handler in MainComp.cmp calls the “NavigateComponent” method, which ultimately invokes the createComponent method with the appropriated parameters passed to it from the event caught. Hence, the MainComp.cmp will now render the Component2.
If you have any queries, please feel free to comment.
how to go back to parent component means maincomponent
LikeLike
@Neetu you can put a BACK button, when clicked it fires the similar event mentioned in the blog to navigate to the Main component.
LikeLike
Thanks for the sample code. How to get the browser back button to redisplay Component1 with entered values instead of the previous page in the browser history?
LikeLike
Hi Dave,
I have written a new post on component navigation which also explains how to go back to the previous page.
https://force-base.com/2016/11/06/lightning-components-navigation-re-defined-in-winter17-woooo-hooooo/
LikeLike
Hi man!
I did a similar app like yours but I have a problem.
I have 3 components: Main, Com1 and Comp2
The FirstLoad Main and automatically the Comp1 is Loaded then a clicked button to next Comp “Comp2”.
But when I am in Comp2 if I “pull to refresh” the page I back to Comp1.
There is away to block this refresh in lightning component? Because if I put the compoent in visualforce this refresh not work. I want to make the same in Lightning component.
Is it possible? Thanks for you help!!
LikeLike
Hi Carlos,
I have written an uodated post on how to navigate through lightning components after Winter’17 in the below. That post should resolve your problem.
https://force-base.com/2016/11/06/lightning-components-navigation-re-defined-in-winter17-woooo-hooooo/
LikeLike
Hi
Can i Open the second component as Popup from first ?
LikeLike
var a = component.find(“n1”).get(“v.value”);
var b = component.find(“n2”).get(“v.value”);
var res = parseInt(a) + parseInt(b);
res = res + ”;
r u gertting correct output from res ??? i am getting null in alert message can you check
LikeLike
Hi Akhil,
Is it possible to fire an event in which component2 can show the sum and difference? If so can you please show the code?
Thank you!
LikeLike
Hi Ram,
Definitely ! You just have to add an additional snippet to calculate the difference along with the sum and pass it as a parameter.
LikeLike
Hi,
Can we pass sObject list in this way? (list is created in apex controller which is called from component1 js controller, then it’s returned to java script controller and from there I want to redirect it to component 2 )
LikeLike
Hi, I’m new is lightning when I follow the step to build the components and I’m getting this error message:
This page has an error. You might just need to refresh it. Action failed: c:MyComponent1$controller$Calculate [evt is undefined] Failing descriptor: {c:MyComponent1$controller$Calculate}
Can anyone please help? Thanks
LikeLike
same error please help with this
LikeLike
Hi Akhil,
I am new to Building Lightning component. Here is what am trying to acheive on salesforce communities
1. Comp 1 – 4 language buttons ( multi language) .On click on language button , the page translates to the respective language.
2. Comp 2 – HTML Markup with some links for each language. This varies depending on the user’s language.
What i want to do is,
when i have all this functionality in one component , am able to acheive what i want , but if i create separate components and place language switcher in footer and html markup comp in content am unable to dynamically change the markup or even display that component in my communities page.
Any directions as to how to go about this scenario.
Thanks
Asha
LikeLike
Its not working in lightning community.
will you please guide as i have view other component on click of a button in community.
LikeLike
Hi, I tried using the above example and I am not able to call the component 2 from the Main Component using the above example, Can you help. Here is the code of the function used in main Component to create the 2nd component as:
NavigateToUnitFinalizationComponent : function(component, event, helper) {
var res = event.getParam(“result”);
alert(res);
$A.createComponent(
“c:BTL_UnitFinalization”,
{
//”res”: res
},
function(newCmp){
if (component.isValid()) {
component.set(“v.body”, newCmp);
}
}
);
}
Please note that in alert I am getting the values. so the control comes till point but after that nothing is happening.
Below is the UnitFinalization component code:
hello dude
The result is {!v.res}
LikeLike