1

I'm trying to implement a canDeactivate guard. For that purpose I need to know the component Instance of the route I want to navigate to.

canDeactivate(
    component: ComponentCanDeactivate,
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot,
    nextState: RouterStateSnapshot
): Observable<boolean> {
    return new Observable((observer: Observer<boolean>) => {
        console.log('componet', component);
        console.log('state', state);
        console.log('nextstate', nextState);
        this.routerService.doSomething(nextState, route);
        observer.next(true);
    });
}

I wonder wheter its possible to get the component from nextState? I tried something like this:

nextState.root.component

but it returns the AppComponent to me, since that's not the name of the component I am navigating to.

How do I do this? Or should I get an instance in other way?

Edit:
i can see the Component Instance(NextComponent) in the developer terminal of my browser inside of RouterStateSnapshot -->

_root: TreeNode  
url: "/Nextcomponent/15708/childcomponent"  
_root: TreeNode  
children: Array(1)  
0: TreeNode  
children: Array(1)  
0: TreeNode  
children: Array(1)  
0: TreeNode  
children: Array(1)  
0: TreeNode  
children: Array(1)  
0: TreeNode  
children: []  
value: ActivatedRouteSnapshot  
component: class NextComponent
                 ^^^^^^^^^^^^^

But not able to get it inside my code.

Random
  • 3,158
  • 1
  • 15
  • 25
dev_EEAN
  • 21
  • 1
  • 4
  • Oh, I've just noticed you wish to know the `next` component, not the one you are leaving... Can you explain why ? Why don't you use an `canActivate` guard on the next route instead ? You have to do something on the previous component, depending on the next one ? – Random Feb 16 '21 at 21:45
  • @Random Thanks, the canActivate is exactly the way i am know going for :-). For some Modules I need to redirect the user to the page he is comming from. Thats wy i have to compare the router information of the current/next Page. – dev_EEAN Feb 17 '21 at 05:32

1 Answers1

0

I see 2 things:

  1. you should never use new Observable(), and and I don't see why you put your code inside an observable (you may just remove the Observable).
  2. I would recommand implementing a method canDeactivateMyFeatureGuard in your component. You can make your component implement a generic AppCanDeactivateMyFeatureGuard(where your guard is named MyFeatureGuard), which defines canDeactivateMyFeatureGuard.
    Then you call this method in the guard.

It would look like this:

export class MyComponent implements AppCanDeactivateMyFeatureGuard {
  // ...
  canDeactivateMyFeatureGuard(): boolean {
    return this.isLocked; // or whatever condition owned by the component, or service call...
  }
}

and the guard:

export class MyFeatureGuard implements CanDeactivate {
  // ...
  canDeactivate(
                component: ComponentCanDeactivate,
                route: ActivatedRouteSnapshot,
                state: RouterStateSnapshot,
                nextState: RouterStateSnapshot
              ): boolean {
    // logic is now in each component, where it can handle the way you wish.
    return component.canDeactivateMyFeatureGuard(); 
  }
}
Random
  • 3,158
  • 1
  • 15
  • 25
  • Thanks for your answer. Actually, I didn't want to implement candeactivate in every component, but only to store the logic once in the routing service. But i think i will try your solution if there is no other way :-) – dev_EEAN Feb 16 '21 at 13:44
  • You may choose the complexity handled by the component. You can do it all in `canDeactivateMyFeatureGuard()` method (the the logic is all in the component), or just add an attribute to your component, like "public isSecureComponent = true", and the the guard uses this boolean in order to do stuff, which has to be done on Secure components (so the complexity remains in the Guard). Everything is possible :) – Random Feb 16 '21 at 13:55