Platform: How to get previous state from Router_Cancel in ngrx?

Created on 8 Feb 2018  路  10Comments  路  Source: ngrx/platform

I was trying to restrict the user from navigating away from the current page by using CanDeactivate (if form is dirty and not saved). By the time we click on any link, Router_Navigation event is getting called and it is updating the router state in store and if I cancel the page navigation on modal pop up (from can deactivate), Router_Cancel event is being called, but the current router state is not getting updated (it鈥檚 still pointing to other page).

I saw this in ngrx documentation:

ROUTER_CANCEL and ROUTER_ERROR contain the store state before the navigation. Use the previous state to restore the consistency of the store.

Can someone please help me on how to get previous state from Router_cancel Action.

Thanks.

Most helpful comment

This is my unrefined hacky solution https://stackblitz.com/edit/ngrx-router-reducer-can-deactivate?file=app%2Fservices%2Frouter-store-extension.service.ts

What it does is:

  • it adds new state property in routerReducer called activeRoute
  • serialized route within activeRoute should use your custom RouterSerializer so state interface should match

All 10 comments

how did you setup the effect?

Sorry, the effect is getting called but in the action i could observe the other router state, which is not the current one.

To be precise i am on editProfile page and before saving if i click on home page, before selecting whether to navigate away or router state is getting updated to home page, and even at router_cancel i could see the payload event and router state still pointing to home.

Is there any way to get the previous state?

payload:
event: NavigationCancel {id: 2, url: "/home/dashboard", reason: ""}
routerState:
params: {}
queryParams: {}
segments: ["home"]

I think you need scan operator

But the document says "ROUTER_CANCEL and ROUTER_ERROR contain the store state before the navigation. Use the previous state to restore the consistency of the store.". Also i am reading the router state from ngrx/router-state, i don't think scan will help me on this.

One Hack i could think of is putting every route state into stack and pop out the previous state when cancel navigation is called.

But this is kind of hack, please let me know if there is any inbuilt mechanism in ngrx.

Thanks

Support questions should be asked on stackoverflow or the gitter channel.

I get that issues are not for support questions but it would certainly help a lot of people to get some guidance or snippet solution for this.

StackOverflow is still unanswered https://stackoverflow.com/questions/48693098/how-to-get-previous-state-from-router-cancel-in-ngrx

Also same question pops on Gitter from time to time. My personal solution is hacky at best and overrides completely ngrx router-store provided reducer.

The best option would be to add this into @peterbsmith2 麓s ngrx recipes git book project mentioned in https://github.com/ngrx/platform/issues/692#issuecomment-372806730

Nobody seems to answer this question on stack or gitter, which makes me think that we are perhaps misunderstanding something...but I can't figure out what.

Based on @sandangel's reply above, I guess to rollback the state in the event of ROUTER_CANCEL, we could use scan operator to accumulate previous ROUTER_NAVIGATION actions. I find the storeState in ROUTER_CANCEL is not useful at all, because it will not have the state that was previously navigated from, but the router navigation that was canceled.

It really is puzzling me to the point where I'm not sure why the router state can be considered the source of truth when it does not reflect the activated route.

This is my unrefined hacky solution https://stackblitz.com/edit/ngrx-router-reducer-can-deactivate?file=app%2Fservices%2Frouter-store-extension.service.ts

What it does is:

  • it adds new state property in routerReducer called activeRoute
  • serialized route within activeRoute should use your custom RouterSerializer so state interface should match

Thanks for posting the example @MattiJarvinen-BA.

@PsychicCat also remember that https://angular.io/api/router/ActivatedRoute provides an observable interface. I'm not entirely sold on the idea where you'd use that with NGRX selectors to pick entities from the store. -> my added activeRoute property

Was this page helpful?
0 / 5 - 0 ratings

Related issues

itprodavets picture itprodavets  路  3Comments

smorandi picture smorandi  路  3Comments

gperdomor picture gperdomor  路  3Comments

sandangel picture sandangel  路  3Comments

ghost picture ghost  路  3Comments