1

So, there can be entry to my app in multiple ways.

http://localhost:4200 and http://localhost:4200/home

If the link to my app (from an outside app) has a query param on it, I want to grab it. I created a QueryParamCheckGuard which is @Injectable({providedIn: 'root',}). For now, I just have a console.log('In QueryParamCheckGuard'); in both the canActivate and canActivateChild methods to see when it gets called. Right now, it's not getting called on any path that redirects.

In my app, I have sub-projects. The main routing looks like this:

  {
    path: 'home',
    canActivate: [QueryParamCheckGuard],
    canActivateChild: [QueryParamCheckGuard],
    data: {
      path: 'App Home Path',
    },
    loadChildren:
      '../../projects/home-app/src/app/app.module#HomeAppModule',
  },
  {
    path: '',
    canActivate: [QueryParamCheckGuard],
    canActivateChild: [QueryParamCheckGuard],
    data: {
      path: 'App Empty Path',
    },
    redirectTo: '/home',
    pathMatch: 'full',
  }

In the HomeAppModule, the routing is this:

{
    path: 'home',
    component: AppComponent,
    canActivate: [QueryParamCheckGuard],
    canActivateChild: [QueryParamCheckGuard],
    data: {
      path: 'Sub-proj Home Path',
    },
    children: [
      { path: '', component: HomePageComponent },
    ],
}

The routing all works correctly, but when I enter http://localhost:4200?id=test, the QueryParamCheckGuard is not being called on the main app's path: '' route that redirects to the main app's path: 'home' and by the time it gets to the sub-project's path: 'home', the id query param is stripped off. I know it's not getting called from the other routes because I added a path property to each path's data that identifies each path. I then console.log(route.data.path);.

If I hit http://localhost:4200/home?id=test, the QueryParamCheckedGuard is hit and I can grab the id query param. Aside from requiring all outside apps to call the /home url, am I missing something to get the path that redirects to home to grab the query param?

ScubaSteve
  • 7,724
  • 8
  • 52
  • 65

2 Answers2

2

So, I found out that this is an existing issue for about 3 years now. https://github.com/angular/angular/issues/18605 Basically, guards don't get called on paths that redirect.

My way around this was to change redirectTo: '/home', to

data: {
  redirectTo: '/home',
},
children: [],

The reason for this is having children:[] allows the guard to be called. Then, in the guard, I check if route.data.redirectTo exists, and if so, return a UrlTree with the value in route.data.redirectTo.

I also realized that changing the redirect on the main app's empty path was not doing anything. I had to add an empty check on the HomeAppModule's routing and do it there. I am now able to grab the query params and save them for when they are stripped after the redirect.

ScubaSteve
  • 7,724
  • 8
  • 52
  • 65
0

I believe your question is dealing with the same issue as mentioned here on GitHub. Generally guards are NOT executed on redirect routes (routes with redirectTo).

A possible solution to circumvent this problem:
You could make the redirect route a child route of the route with the guards as follows:

{
  path: '',
  canActivate: [QueryParamCheckGuard],
  canActivateChild: [QueryParamCheckGuard],
  data: {
    path: 'App Empty Path',
  },
  pathMatch: 'full',
  children: [
    {
      path: '',
      redirectTo: '/home',
    }
  ]
}

Like this the guards will be executed on the "parent" with the empty path and then it will execute the redirect when matching the "child" route afterwards.

Wilt
  • 41,477
  • 12
  • 152
  • 203