2

I have the following in my main app router:

{ path: 'users', loadChildren: 'app/modules/users/users.module#UsersModule', canLoad: [AuthGuard] }

When the user goes to http://localhost:4200/users/1234 to see their profile, I try to save the full url (including the user ID above) so that I would route back to that page once they're logged in.

The problem is, the Route parameter in the canLoad function only has a path field that does not include the user ID above, only the path users. Is there a way I can achieve this?

EDIT AFTER FIRST COMMENT

The users routing module does have a canActivate guard, but this never gets called except from the login component, since the first canLoad returned false and routed the caller to the login component previously.

EDIT AFTER FIRST ANSWER

canLoad(route: Route) {
  if (!AuthService.isAuthenticated()) {
    this.router.events.takeWhile(event => !(event instanceof NavigationCancel))
      .subscribe(event => {
        console.log(event);
        if (event instanceof NavigationCancel) {
          AuthService.setRedirectUrl(event.url);
        }
      });
    return false;
  }
  return true;
}

So I tried the above, but I think I'm doing something wrong still, since console never logs... how do I unsubscribe or stop receiving NavigationCancel events after I set store the redirect URL?

Sammy
  • 3,395
  • 7
  • 49
  • 95
  • if you want to save the state in a guard, try using `canActivate` guard. Since canLoad is called during the construction of the router state, and `canActivate` is called after, the canActivate guard gets more information. It gets its activated route and the whole router state, whereas the canLoad guard only gets the route. – Max Koretskyi Jun 11 '17 at 17:04
  • Sure, but if `canLoad` fails in the first place, `canActivate` will never be called! – Sammy Jun 11 '17 at 17:06
  • right, but if it fails, do you need to save the page still? – Max Koretskyi Jun 11 '17 at 17:08
  • `canLoad` failed because the caller is not logged in. The caller then gets routed to a login component, which, after authenticating, should route the user to the original URL. – Sammy Jun 11 '17 at 17:09
  • try injecting a router into a guard, subscribe to guard [events](https://github.com/angular/angular/blob/4.0.0/packages/router/src/router.ts#L326) and listen for [NavigationStart](https://github.com/angular/angular/blob/4.0.0/packages/router/src/events.ts#L17) or [RoutesRecognized](https://github.com/angular/angular/blob/4.0.0/packages/router/src/events.ts#L91) event – Max Koretskyi Jun 11 '17 at 17:15
  • Thank you, and I do not need to unsubscribe from that? I remember reading that the exception to required unsubscribing was the router. – Sammy Jun 11 '17 at 17:27
  • It's actually NavigationCancel that I should subscribe to by the way :) – Sammy Jun 11 '17 at 17:34

1 Answers1

1

Since canLoad is called during the construction of the router state it doesn't get activated route and the whole router state. It gets only the route.

You can inject a router into a guard, subscribe to NavigationCancel event where you can access the URL.

how do I unsubscribe or stop receiving NavigationCancel events after I set store the redirect URL?

Since router.events is a Subject, you can unsubscribe from it like this:

// get the subscription reference
const subscription = this.router.events.takeWhile(event => !(event instanceof NavigationCancel))
      .subscribe(event => {
        console.log(event);
        if (event instanceof NavigationCancel) {
          AuthService.setRedirectUrl(event.url);
          // use it to unsubscribe
          subscription.unsubscribe(); <----------------------------
        }
      });
Max Koretskyi
  • 101,079
  • 60
  • 333
  • 488