Lightning Web Components – Navigating to LWCs Wrapped in Aura Component

I have a requirement where I need to navigate to LWCs. I referred this website and used aura component for the navigation. I do not wish to use tabs, hence I chose this option. There are 4 LWCs and each LWC navigates to the next LWC (LWC 1 -> LWC 2 -> LWC 3 -> LWC 4). I do not wish to use multiple aura components hence I implemented it using a single aura component.

The problem is that the navigation works for the 1st time and after that, every navigation needs a manual refresh. I think the problem occurs due to caching. There is a change in URL but the new LWC does not load until the page is manually refreshed. I am trying to find a way to solve the issue without disabling caching for LWCs.

Code used for navigation to the next LWC:

//This code is used for navigation to the next LWC. It is executed when next button is clicked on the LWC.
handleNextButton(){
  this[NavigationMixin.Navigate]({
    type: "standard__component",
    attributes: {
      componentName: "c__NavigateToLWC" //This is the name of the aura component
    },
    state: {
      c__nameOfLWC: 'customReportFilterLWC' //This is the name of the LWC to which we want to navigate
    }
  });
}

Note: Above code is the same for all LWCs except the state: part of it.

Aura Component Code:

<aura:component implements="flexipage:availableForAllPageTypes,lightning:isUrlAddressable" access="global">
    
    <!-- Create flags and set the default value to false. -->
    <aura:attribute name="customReportFilterLWCFlag" type="boolean" default="false"/>
    <aura:attribute name="customReportSortingLWCFlag" type="boolean" default="false"/>
    <aura:attribute name="customReportPreviewLWCFlag" type="boolean" default="false"/>
    
    <!-- Call the init handler. It will set a flag to true -->
    <aura:handler name="init" value="{!this}" action="{!c.init}"/>   
    
    <!-- Display the LWC that has the corresponding flag set to true in the init handler -->
    <aura:if isTrue="{!v.customReportFilterLWCFlag}">
        <c:customReportFilterLWC/>
    </aura:if>
    
    <aura:if isTrue="{!v.customReportSortingLWCFlag}">
        <c:customReportSortingLWC/>
    </aura:if>
    
    <aura:if isTrue="{!v.customReportPreviewLWCFlag}">
        <c:customReportPreviewLWC/>
    </aura:if>
    
</aura:component>

Aura Controller Code:

({
    init: function(component, event, helper) {
        
        //Get the name of the LWC to which we need to navigate
        var pageRef = component.get("v.pageReference");
        var navigateToLWC = pageRef.state.c__nameOfLWC;
        
        //Check the name of the LWC and set the corresponding flag to true
        if(navigateToLWC == 'customReportFilterLWC'){
            
            component.set("v.customReportFilterLWCFlag", "true");
            
        }else if(navigateToLWC == 'customReportSortingLWC'){
            
            component.set("v.customReportSortingLWCFlag", "true");
            
        }else if(navigateToLWC == 'customReportPreviewLWC'){
            
            component.set("v.customReportPreviewLWCFlag", "true");
            
        }
        
        //Refresh the page to open the next LWC.
        //$A.get('e.force:refreshView').fire();
        
    }
})

I thought that forcing a refresh would solve the issue but it does not. The browser hangs and does not load. I get the following error message:

enter image description here

I am not able to find a way out. Please guide. Thank You!

Best Answer

lightning:isUrlAddressable is an Aura interface and this link states the following:

The lightning:isUrlAddressable interface extends the lightning:hasPageReference interface. A component that implements lightning:isUrlAddressable then gets access to the page state through the pageReference attribute. The page state is a representation of the current URL query parameters.

lightning:isUrlAddressable enables you to generate a user-friendly URL for a Lightning component with the pattern /cmp/componentName

Important: When the target of a navigation action maps to the same component, the routing container might simply update the pageReference attribute value instead of recreating the component. In this scenario, a change handler ensures that your component reacts correctly.

Note the last point about the update to the pageReference attribute value and the need to have a change handler. Your aura component has the init method which will execute only once for the component initialization. But, there is no handler method corresponding to any change in the pageReference attribute value. So, when the NEXT button handler executes, the pageReference value is updated but no handler is present to update the boolean attributes.

In the following code snippet, you have mentioned that the attributes value will remain same in all LWCs, but the state value will change.

this[NavigationMixin.Navigate]({
    type: "standard__component",
    attributes: {
      componentName: "c__NavigateToLWC" //This is the name of the aura component
    },
    state: {
      c__nameOfLWC: 'customReportFilterLWC' //This is the name of the LWC to which we want to navigate
    }
  });

So, your aura component HTML should include the following code. This will invoke the init method every time there is a change to pageReference. Note that if you have additional code in the init method that should not be executed everytime, then create a separate JS method as the change handler.

<aura:handler name="change" value="{!v.pageReference}" action="{!c.init}"/>

And, the init method in the aura controller JS should be as follows:

init: function(component, event, helper) {
        
    //Get the name of the LWC to which we need to navigate
    var pageRef = component.get("v.pageReference");
    var navigateToLWC = pageRef.state.c__nameOfLWC;
    
    //Check the name of the LWC and set the corresponding flag to true
    if(navigateToLWC == 'customReportFilterLWC'){
    
        component.set("v.customReportSortingLWCFlag", "false");
        component.set("v.customReportPreviewLWCFlag", "false");
        component.set("v.customReportFilterLWCFlag", "true");
        
    }else if(navigateToLWC == 'customReportSortingLWC'){
        
        component.set("v.customReportPreviewLWCFlag", "false");
        component.set("v.customReportFilterLWCFlag", "false");
        component.set("v.customReportSortingLWCFlag", "true");
        
    }else if(navigateToLWC == 'customReportPreviewLWC'){
        
        component.set("v.customReportSortingLWCFlag", "false");
        component.set("v.customReportFilterLWCFlag", "false");
        component.set("v.customReportPreviewLWCFlag", "true");
        
    }   
}

Alternate approach:

If you are embedding all the LWCs inside an aura component, I don't see a need for NavigationMixin.Navigate in all 4 components. Instead, you can do the following:

  • Dispatch a custom event from the LWC and this custom event should include (in its detail attribute) the name corresponding to the boolean attribute.
  • Handle the custom event on the parent Aura component by obtaining the detail attribute value to update the boolean attributes, thereby controlling which LWC is displayed.