1

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!

5
  • 2
  • @sanketkumar Thanks for the response! I had taken a look at it before. It's using URL for navigation and isn't a long term solution. – SFdev Nov 11 '20 at 17:54
  • For your current approach, how are you handling the navigation from LWC2 to LWC3? Can you post the code snippet for LWC2 or LWC3? I suspect you should dispatch a custom event from these child LWC to aura component and handle it accordingly. You current code snippet doesn't show any of this? Note that aura init event executes only once for component initialization. Also, why do you say @sanketkumar's recommendation isn't a long term solution? Can you elaborate your use case? – arut Nov 15 '20 at 12:08
  • @arut Thank you for the response! I used NavigationMixin.Navigate for navigation when the user presses the Next button on the LWC. Please see the first code snippet in the question. I have added comments to it for better understanding. As for @sanketkumar's recommendation, it will work only as long as the URL stays the same. Any change in the URL portion '/one/one.app#' in the future will fail the navigation. Hence I said that it's not a long-term solution. – SFdev Nov 15 '20 at 13:25
  • I wouldn't be worried about any change to /one/one.app# in the near future, but would agree to a probable deprecation to the the old way of base64 encoded info about the component details in the URL. But, this may not happen anytime soon IMO. Also, using the page reference types available in LWC, I guess there should be a different approach, but depends on your requirements. Check if the posted answer would solve the problem in your current approach. – arut Nov 15 '20 at 15:12
2
+50

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.
4
  • It works! Thanks a lot for the detailed answer. The alternate approach suggested by you will use events in all 4 LWCs instead of NavigationMixin.Navigate. The aura component will be needed regardless. But is there any performance advantage in using events instead of NavigationMixin.Navigate? – SFdev Nov 17 '20 at 7:31
  • I also looked at alternate approaches which will eliminate the use of aura component for navigation. Approach 1: Use parent LWC and embed child LWCs inside it -Link. Approach 2: Use Flows to navigate between LWCs -Link. Please provide short feedback on these approaches. Thanks again! – SFdev Nov 17 '20 at 7:34
  • 1
    I don't see any performance advantage of using events over NavigationMixin.Navigate. While NavigationMixin will still work for your case, its primarily built to navigate to different pages (based on page type & by manipulating the PageReference JS object). I don't see a point in using this if the user is going to be staying on the same page for all the LWCs (unless there is valid use case not mentioned in your question). In fact, Approach 1 mentioned in your comment is well suited for your use case IMO, thereby eliminating Aura comp & building everything on LWC. – arut Nov 17 '20 at 8:01
  • 1
    Approach 1 vs Approach 2 is just a matter of preference based on the business requirements. Your use case can be implemented in either of these. If you use Approach 2, you would use screen elements that is best suited for user guidance scenario and comes with a previous, next & finish buttons. You would also have flow variables which can be used to capture the input & output data between various components. In Approach 1, you would do the same using custom events to send data from child components to parent & public methods to call child comp methods from parent. – arut Nov 17 '20 at 8:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.