[SalesForce] Lightning component lazy loading as lightning:tabset

I have a bunch of components <c:CmpA />, <c:CmpB />

Sometimes, I need to perform a check for access rights to this component, so I decided to create a <c:CheckWrapper></c:CheckWrapper> as this:

<aura:component description="CheckWrapper"
                controller="CheckWrapperController"
>
  <aura:if isTrue="{! not(v.loading) }">

    <aura:if isTrue="{! v.isAllowed }">
    {! v.body }
      <aura:set attribute="else">
        {! v.error }
      </aura:set>
    </aura:if>

  </aura:if>
</aura:component>

Its JS controller perform a check on Apex, and then release v.isLoading and v.isAllowed (or not).

The usage is has this:

<c:CheckWrapper somethingToCheck="['this', 'that']">
  <c:CmpA attr="{! v.attr }" />
</c:CheckWrapper>

Everything works perfectly except that even if you are not allowed to use this component (and it will not be mounted on the DOM because of <aura:if isTrue="{! v.isAllowed }">), it is instantiate and its <aura:handler name="init" value="{!this}" action="{!c.doInit}"/> is performed.

How can I prevent this without dynamically creating the component ? As an example, <lightning:Tab> and <lightning:Tabset> work exactly the same way but the child component's init handler is performed on render.

<lightning:tabset selectedTabId="{! v.stepName }" >
  <lightning:tab label="label" aura:id="id" id="id" >
      <c:CmpA attr="{! v.attr }" />
      <!-- Tab is loaded, component is mounted, init is performed -->
  </lightning:tab>
  <lightning:tab label="label2" aura:id="id2" id="id2" >
      <c:Cmpb attr="{! v.attr }" />
      <!-- Tab is hidden, component is unmounted, init is not performed until open the tab -->
  </lightning:tab>
</lightning:tabset>

Do you have any idea I can have the same behaviour ?

Best Answer

Can you try this inside your CheckWrapper Component.

<aura:if isTrue="{! v.isAllowed }">
    <c:CmpA attr="{! v.attr }" />
    {! v.body }
    <aura:set attribute="else">
    {! v.error }
</aura:set>
</aura:if>

Edit Solution 2:

Here you can pass your component as an attribute to checkWrapper and let checkWrapper decide whether to show or not components.

Test App Code

<aura:application >
    <c:CheckWrapper componentName="c:CmpA"></c:CheckWrapper>
</aura:application>

CheckWrapper.cmp

<aura:component description="CheckWrapper" controller="CheckWrapperController">
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<aura:handler name="change" value="{!v.isAllowed}" action="{!c.isAllowedChanged}" />

<aura:attribute name="somethingToCheck" type="String"></aura:attribute>
<aura:attribute name="componentName" type="String"></aura:attribute>
<aura:attribute name="component_attributes" type="String"></aura:attribute>
<aura:attribute name="isAllowed" type="Boolean" default="false"></aura:attribute>

<aura:if isTrue="{! not(v.loading) }">

<aura:if isTrue="{! v.isAllowed }">
        {! v.body }

        <aura:set attribute="else">
        {! v.error }
      </aura:set>
    </aura:if>
</aura:if>
</aura:component>

CheckWrapperController.js

doInit : function(component, event, helper) {
    var show = component.get("v.isAllowed");
    if(show)
    helper.createCmp(component,event);

},
isAllowedChanged : function(component, event, helper) {
    var show = component.get("v.isAllowed");
    if(show)
    helper.createCmp(component,event);
}

CheckWrapperHelper.js

createCmp : function(component,event) {

    var cmpName= component.get("v.componentName");
    var cmpAttr = component.get("v.component_attributes");
    var cmp = component;
    $A.createComponent(cmpName, cmpAttr, function(newComp, status, errorMessage){

            if (status === "SUCCESS") {
                var body = cmp.get("v.body");
                body.push(newComp);
                cmp.set("v.body", body);
            }

        });
}

CmpAController.js

doInit : function(component, event, helper) {
    console.log('comp A initiated');
}

CmpA.cmp

<aura:component >
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <h1>I'm Component A</h1>
</aura:component>

You can change the default value of isAllowed to true on checkWrapper to check component creation. Hope this helps!!

Related Topic