4

I have been thinking about something I find very counter-intuitive, I have found previous an issue about it, but information given in response is weak at best. https://github.com/angular/angular/issues/27826

A simplified explanation of what I am trying to accomplish. The issue is that I would like to create 2 areas, one that requires login and one that does not. When the user is logged in he have access to a special protected areas depending on his role (for simplicity lets say an admin section), the administration module is ONLY available if you have the correct system permission, and therefor I added a lazy-loaded module, with a canLoad property.

export const myRoute: Routes = [
  {
    path: '',
    component: RequiresLoginComponent,
    canActivate: [LoggedInGuard],
    children: [
      {
        path: '',
        component: ContentComponent,
      },
      {
        path: 'admin',
        canLoad: [PermissionGuard],
        loadChildren: () =>
          import('admin/admin.module').then((mod) => mod.AdminModule),
      },
    ],
  },
  {
    path: 'login',
    component: LoginComponent,
  },
];

if you visit /admin canLoad on child will ALLWAYS occur before canActivate, my routing is significantly more complicated than this, with nested sections of protected resources and sections. Can someone explain me the logic behind this design?

Mped
  • 41
  • 1
  • I am also stuck on the same problem. I have a ping service which has to validate the session (cookie) before it can set the state of the application as authenticated. the LoggedInGaurd above will call a service to validate if the session token is valid and then persist the state in a service. later on down in the line during the admin route canload will use the state to define if the module can be loaded. but the problem here is that the canload is called first and because it is checking if the user is logged in (and finds not logged in), it redirects the user to the login page. – Anant Anand Gupta Aug 08 '22 at 21:04
  • I have got a work around by using app_initializer provider. – Anant Anand Gupta Aug 09 '22 at 14:46

1 Answers1

1

A lot of information is missing from your question. "Visit the /admin" as in using the router or typing in the address bar? Also, what do you do inside your guards? What are your requirements?

If there is no answer in Angular's GitHub issue, chances are that you will need a workaround to do what you want.

In any case, I prepared this StackBlitz demo, but since I made a few assumptions, I'm not sure if it's what you're looking for.

-- EDIT --

I'm afraid you will have to use a workaround for this one.

One way to solve this for your case would be to create a service (see WorkaroundService in demo below) and extract the logic of the canActivate method into a method in that service.

Then, inject this service into the CanLoad guard and use the method before any other logic.

Alternatively, you can inject the canActivate guard to your canLoad guard and use its method directly.

Of course this is just a workaround, and you will see your canActivate logic is executed twice. You can use some checks to prevent unwanted side-effects. See this StackBlitz demo.

Another solution I've found is to use a master guard to define the order, but I haven't given this a try.

Vasileios Kagklis
  • 784
  • 1
  • 4
  • 14
  • [here](https://stackblitz.com/edit/aag-test-guards?devToolsHeight=33&file=src/app/app-routing.module.ts) is the sample which reproduce the issue – Anant Anand Gupta Aug 09 '22 at 22:11
  • I will try your workarounds. For now the workaround i have used is to go deeper using app_intializer, but the problem is that it fires for every route which eventually I don't want. I need to check for session only in case the route corresponds to a protected information. – Anant Anand Gupta Aug 13 '22 at 21:22