How to "remember" selected sub menu page when navigating away and back?

#1

I have a primary menu:

   Section 1 | Section 2 | Section 3 

I select Section 3. It has a sum menu:

   Sub 1 | Sub 2 | Sub 3

I select Sub 3. Active route is now Section 3 | Sub 3

I click link in primary menu to go to Section 1.

I click link in primary menu to go back to Section 3. I expect the app to reload Section 3 with the sub page I was last on to be loaded (ie, Section 3 | Sub 3 ) but it goes to Section 3 | Sub 1.

That happens because I have not got any logic in my menu to handle that:

<template bindable="router">
  <nav>
    <ul>
      <li repeat.for="row of router.navigation" class="${row.isActive ? 'active' : ''}">
        <a href="${row.router.history.location.origin}${row.router.history.location.pathname}${row.router.history.location.search}${row.href}">${row.title}</a>
      </li>
    </ul>
  </nav>
</template>

Question is - how do I build the href so that the menu works as expected? Or is there some other configuration option in Aurelia to enable this rather than manually crafting modified links?

There is also a related question. Loaded pages need to remember ALL of their visual state when navigating back and forwards. Using @singleton appears to work for that - but not sure this is entirely safe to do for every viewmodel thoughout my whole app.

1 Like
#2

No one ever done this?

1 Like
#3

The problem you want to solve with this cannot be easily solved without storing route state some level above the Section router because each view model view be thrown away every time you navigate to different section.

There is also a related question. Loaded pages need to remember ALL of their visual state when navigating back and forwards. Using @singleton appears to work for that - but not sure this is entirely safe to do for every viewmodel thoughout my whole app.

It’s not a bad solution for me. Maybe scope the class close to parent where the <router-view/> is.

#4

Thanks for the reply. I was hoping there might be something built-in to Aurelia router that I was missing for remembering correct menu state. Unfortunately not. Thanks for confirming.

For remembering page state, @singleton works only partly: I can get the outermost viewmodel state to be cached using the annotation, but I am losing all UI state for the many custom elements on the view (themselves composed of many nested custom widgets). There appears to be no easy way to cache that lot without a great deal of pain doing it manually. I have all the necessary the data state stored already - using Aurelia Store - just a matter of having to recreate all the UI state - open panels, visible widgets - and any sub-router menu state, etc). Painful if this is deeply nested.

But I don’t know what this means:

Maybe scope the class close to parent where the <router-view/> is.
1 Like
#5

Ignore that, it’s just only dealing with view model, so view and all its UI state will still be gone. If persisting the UI state is important (charting, interactive widgets), i would suggest using virtual route (made up name):

<router-view
  show.bind='section1Or2'></router-view>
<section-3
  if.bind='!section1Or2'></section-3>

Then you just need to specify empty view model for section 3 route. The disadvantage is you lose routing life cycle of <section3/> but it’s not hard to come up with a synthesized one i guess.

#6

I did something similar with a view that needed to remember filter values. I wound up using the activate() and deactivate() lifecycle methods to write the state to local storage. Basically, when the user leaves the page (goes to Section 1 or 2), Sub 3 writes possibly two values to local storage – one value for Section 3 to know that Sub 3 was the active subpage so that activate() of Section 3 can navigate to the appropriate sub route and another value that stores the settings/values of Sub 3 so that they can be restored when reloaded.

Can’t say I’ve ever tried to do that across an entire app but have done it for a few pages within an app.

1 Like