7

Currently, in Angular, you can restrict access to all child routes by applying a router guard to one of the parents:

export const routes: Routes = [
  {
    path: 'my-account',
    canActivate: [IsUserLoggedIn],
    children: [{
      path: 'settings',
      component: SettingsComponent
    }, {
      path: 'edit-profile',
      component; EditProfileComponent
    }]
  }
];

This is useful to avoid having to repeat the canActivate guard in each route. But now what happens when I want to introduce a third route under my-account that should be publicly accessible? For example, maybe there's a publicly-accessible Help page at my-account/help that everyone should be able to access, even when they aren't logged in:

}, {
  path: 'help',
  component: HelpComponent,
  // Somehow make exception to canActivate guard above
}, {

Is there a clean way to do this, or is the only way to disrupt the organization of routes and apply the router guard to each child route manually, except the Help page?

A. Duff
  • 4,097
  • 7
  • 38
  • 69

2 Answers2

3

The only solution I can think of is this:

canActivate(
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot): boolean {

       // In the next you have .url prop so you can check for it 
       if (state.url.indexOf('help') !== -1) { return true; }

       // Your current Guard logic
    }
Kevin Doyon
  • 3,464
  • 2
  • 33
  • 38
Vitalii Chmovzh
  • 2,825
  • 4
  • 14
  • 28
  • Yeah, thought of that too, but seems poor organization. I feel like that logic should be handled in the routes. – A. Duff Feb 09 '18 at 22:32
  • 3
    Well, Guard supposed to guard root and children routes , so if there should be exception to which child routes should be guarded, the guard is the perfect place to add such exception. Other solution will be to put help under public parent without guard on it (losing desired route nesting for sure). – Vitalii Chmovzh Feb 09 '18 at 22:34
3

I personally think if the HelpComponent route doesn't need to be protected, it will need to be in different parent route. So, it's the matter of organizing the routes.

But, in any case, you could also create a separate route for it, such as:

export const routes: Routes = [
  {
    path: 'my-account',
    canActivate: [IsUserLoggedIn],
    children: [{
      path: 'settings',
      component: SettingsComponent
    }, {
      path: 'edit-profile',
      component: EditProfileComponent
    }]
  },
  {
    path: 'my-account/help',
    component: HelpComponent
  }
];
stack247
  • 5,579
  • 4
  • 41
  • 64