0

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?

2

2 Answers 2

2

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.

1
  • 1
    Looks like this approach worked for me. I was able to use local storage to preserve the profileName across pages
    – SfdcBat
    Feb 10, 2022 at 19:45
1

Aura already has the concept of caching. Using an @AuraEnabled(cacheable=true) method, calling the same function with the same parameters will result in the cached data being returned immediately. This is why you shouldn't need to be passing around data in this manner.

If you absolutely still insist on having your own cache, you can do so by way of an Application Event. Your grandchild would fire off an event and then get the response in return. Or, you can use the Lightning Message System to communicate between the two components directly. Finally, don't forget that when dynamically creating components, you can use component.getReference("v.someAttribute"), and pass that in to $A.createComponents in order to dynamically create a two-way data binding that the parent (and subsequently child) components can access.

Honestly, it's probably not worth it in most cases; just call the Apex method every time you need the data, and let the underlying Lightning Data Service cache handle caching for you.

10
  • I was going towards Apex route but do have any thoughts on whether I can use localstorage in this case? Any drawback of using localstorage?
    – SfdcBat
    Feb 10, 2022 at 19:46
  • @SfdcBat Prefer sessionStorage, it's got a shorter lifespan. Remember also that both storages are locked to a single namespace. If you're not an ISV, it doesn't matter, but just be aware of that limitation.
    – sfdcfox
    Feb 10, 2022 at 19:50
  • Thanks for the suggestion! its not ISV
    – SfdcBat
    Feb 10, 2022 at 19:51
  • 1
    @SfdcBat sessionStorage is locked to a specific subdomain, and further enhanced by Locker Service/Lightning Web Security to sandbox each namespace (e.g. lightning, c, managed packages). The only concern would be if you installed unmanaged/unlocked packages; they could also access sessionStorage, as they have no namespace. If you trust your namespace's code, you should be fine. Circling back, though, using a cacheable method would save you a lot of trouble :D
    – sfdcfox
    Feb 10, 2022 at 20:08
  • 2
    you can list the storage items, or your your browser to check the actual key, because SF will prepend the ProfileName key with some namespace and or id's, so, if you directly try with 'ProfileName' in your console it wont work
    – glls
    Feb 10, 2022 at 20:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .