Aura : Passing attribute across different components in containment hierarchy

auraeventjavascriptlightning-aura-componentsparent-to-child

I am trying to get the user's profile from Apex Controller once and re-use it across multiple components. I have a grandParent.cmp which creates a Parent.cmp. After the user does some selection on parent cmp , on click of next button it would create a child cmp from its doInit() method. It is like a guided setup page where each chevron shows different child cmps based after clicking next.

enter image description here

s the user clicks Next button the parent cmp loads for each chevron and based on user selection will create a child component dynamically. The child component name that needs to be used is stored in a custom object for each chevron. All of that happens in DoInit() method of Parent.

My Challenge is: I am trying to query the logged In user profile from GrandParent and pass it to Parent, which then can pass it to whatever child it is creating. However since GrandParent loads only once, it does not pass the value again when Parent is loaded independently.

grandParent aura cmp:

<aura:attribute name="profileName" type="String" />

grandParent controller JS:

doInit : function(component, event, helper) {
helper.getProfileNameOfUser(component, event, helper);
},

handleNext{
    // logic to create PARENT aura cmp
    // sets profileName 
}

grandParent helper JS:

getProfileNameOfUser : function(component, event, helper){
    // calls Apex and SOQLs the profile Name
    // set the attr profileName
}

Parent cmp:

<aura:attribute name="profileName" type="String" />

Parent controller JS:

doInit : function(component, event, helper) {
    console.log('profileName ---> ' , profileName); // Yass , profile Name is available and I don't need to fetch again from server
    // Also the child component is created on the fly based on the data from a custom object. based on what chevron/page it is on  
    // it will gather the component list from custom object and creat the using create component.
},

handleNextClick{
    // When next button is clicked
    // based on what user selects the data will be sent to next component
    helper.handleNext()
}

Parent Helper JS:

handleNext: function(component, event, helper){
    // The component is destroyed and launched again
}

After Next is clicked only the Parent cmp is reloaded and not the grandParent record. So next time the doInit() loads I see in console log that Profile Name is undefined.

Hence, when a child record is created in doInit() , I am unable to pass the profileName attr to the dynamically generated child object.

Parent conttroller JS

doInit : function(component, event, helper) {
    console.log('profileName ---> ' , profileName); // 'Undefined during 2nd load'
    // createComponent('child')
    // childComponents.push([cmp.Name, {
    // "profileName" : component.get("v.profileName") // However at this point profileName is undefined.
    //}
},

Child cmp:

<aura:attribute name="profileName" type="String" />

Child controller

doInit : function(component, event, helper) {
    console.log('profileName ---> ' , profileName); // 'Undefined during 2nd load'
},

The reason profileName is coming undefined is because only parent cmp loads and not the grandparent where we are using the Apex controller to fetch the data. Is there any way I can store the data so that it can be passed down the hierarchy? Any cache concept I could use or any other suggestion?

Best Answer

In order to avoid passing around props or variables around components, specially when they are deeply nested or in a hierarchy, you can leverage the browsers local storage in order to have data persist or become available across components whenever needed. This is a common practice when doing web development.

here is a quick documented sample of sessionStorage:

/ Save data to sessionStorage
sessionStorage.setItem('key', 'value');

// Get saved data from sessionStorage
let data = sessionStorage.getItem('key');

// Remove saved data from sessionStorage
sessionStorage.removeItem('key');

// Remove all saved data from sessionStorage
sessionStorage.clear();

you could basically invoke your apex class once, and store the response in the browser(s) sessionStorage. and call the session storage item in the components that you need during the browsers session.

Related Topic