router, goBack and onParameterChanged

Hey, clarification needed about how the router works behind the scenes.

Imagine a Hierarchical navigation that guides a user through a [signup] flow of identically-looking pages, by executing a router.push('flow',{},'page',{'step':'x'}), where x stands for the ID of the specific “step” within the flow which we want to show. This router.push() call would happen whenever a user completes a given screen and presses a “Next” button.

Also, imagine there is a “Back” button on each screen, which calls router.goBack().

Now, while we move forward through the flow, the router gets pushed to the same template 'flow' / 'page' over and over again, but the params passed with it ({'step':'x'}) change, triggering the this.onParameterChanged() function, which allows for further data manipulation, such as deciding what content to show on that page.

While landed on one screen in the middle of the flow, raising router.goBack() simply removes the last page pushed, and displays the previous screen without triggering the this.onParameterChanged() function. If at this point we click “Next” again, the router restores the previously removed page without triggering the this.onParameterChanged() function. However, if we move further down the hierarchy in any direction (push or goBack) for more than 1 screen, the this.onParameterChanged() function starts to get called again, mostly because the router apparently “remembers” and reuses only the last screen it was on.

This does not raise an issue per se, since there are other ways to structure the flow. However, it’s somewhat limiting if I want to set an Observable value (say, currentStep.value = 'x'; in JS) from this.onParameterChanged() directly. Having the ability to pass params to router.goBack({'step':'x'}) and having a callback function to receive that data could be one way to solve this.

The whole situation is a bit of a problem if I build a JS module that does stuff based on the Observable value that I set from this.onParameterChanged(). For example, the “Next” button could tell the module to “proceed to next step” instead of “go to step X”, but the problem is that our hypothetical JS module will only see the last Observable value that was set from this.onParameterChanged(), not the one we should have if we did one router.goBack(). Consequently, when telling the module to “proceed”, it would actually go to the wrong page / display wrong data.

TL;DR: the this.onParameterChanged() callback usage is somewhat limited, since it doesn’t get called on router.goBack() and a repeated router.push() to a previously removed page.

Hi!

The onParameterChanged event is not meant to be an event that tells you when a page is navigated to. It is only firing when the parameter for a given page is changed. We are not going to change what this event means to serve multiple purposes.

Instead, we could consider adding a onActivated event that fires whenever a page is navigated to, for example. And maybe and <Activated> trigger. Would that cover your use case?

You can already do this:

<WhileActive>
    <Callback Handler="{someFunc}" />
</WhileActive>

However, I agree this is not very clean/intuitive, so I’m creating a ticket to have this looked at.

Activated and Deactivated events and triggers are now implemented and will roll out in a near future release, which will solve make this use case easier to deal with :slight_smile:

Keep an eye on changelogs!