1

I have a pending change guard like

    import {CanDeactivate} from '@angular/router';

export interface ComponentCanDeactivate {
  canDeactivate: () => boolean | Observable<boolean>;
}

export class PendingChangesGuard implements CanDeactivate<ComponentCanDeactivate> {
  canDeactivate(component: ComponentCanDeactivate): boolean | Observable<boolean> {
    // if there are no pending changes, just allow deactivation; else confirm first
    return component.canDeactivate() ?
      true :
      // NOTE: this warning message will only be shown when navigating elsewhere within your angular app;
      // when navigating away from your angular app, the browser will show a generic warning message
      // see http://stackoverflow.com/a/42207299/7307355
      confirm('WARNING: You have unsaved changes. Press Cancel to go back and save these changes, or OK to lose these changes.');
  }
}

My issue is that I also have some tab controls that are tied into the page route params, so when a tab is navigated it updates the route params and vice versa. It updated the param by navigating to the current route with the new param, which doesn't reload the component since it is the current route still. My issue is that I do not want these route changes to be considered a deactivation by the PendingChangesGuard since the component is still on the page in a different tab.

Ideally I would be able to pass some parameters to the guard telling it which route params to ignore in the case of re-navigating to the current route, and then some way to detect within the guard if the only changes are one of the ignored parameters. I'm not sure how to detect changes in the params like that, and ideas?

Josh
  • 1,648
  • 8
  • 27
  • 58
  • you have access to route params in `canDeactivate` you can use it directly to build your logic `canDeactivate(component: ComponentCanDeactivate, route: ActivatedRouteSnapshot,state: RouterStateSnapshot). – Madhu Ranjan Apr 28 '17 at 15:27
  • I am aware of that, but how can I look at the previous route and the current route and figure out which parameters changed? – Josh Apr 28 '17 at 16:35

1 Answers1

1

You could use query params instead of route params. Query params don't cause guards to re-run. That's not the only difference between query params and route params (or matrix params, or whatever they're called), but it makes them worth considering. The angular router is pretty opinionated so you may never find an elegant solution.

Query params:

this.router.navigate([], {
  queryParams: {'tab': whatever}
});

or

<a [routerLink]="[]" [queryParams]="{'tab': whatever}">tab</a>
dbandstra
  • 1,304
  • 9
  • 10
  • Thanks! I thought about using query strings, but in the past i've had issues with cleaning them up when unloading components and ending up with orphaned query strings or issues with timing where a new route is adding a querystring and an unloaded route is cleaning up its querystrings and they interfere. Route params keep it simple in that regard at least. – Josh May 10 '17 at 04:09
  • I remember something like that a year or so ago, when 'preserving' query params across navigations was the default behaviour (it isn't anymore). Is that what you're talking about? Of course if you have multiple routes using query params at the same time then it's a bad idea. I use query params for tabs and nothing else. – dbandstra May 10 '17 at 19:21