I'm having an issue trying to navigate through different routes.
I have two different route modules.
app.routes.ts:
Containing only LoginPage
:
export const routes: Routes = [
{
path: 'login',
component: LoginPageComponent,
canActivate: [PreventLoggedInAccess]
},
{
path: '',
redirectTo: 'login',
pathMatch: 'full'
},
{
path: '**',
redirectTo: 'login'
}
];
export const Routing: ModuleWithProviders =
RouterModule.forRoot(routes, { useHash : true });
With PreventLoggedInAccess.canActivate, that, if the user is already logged in redirects him to the logged in section with /app
prefix and child route home
. It's defined as:
canActivate(): boolean {
if (!this._authService.isAuthenticated()) {
return true;
}
this._router.navigate(['/app/home']);
return false;
}
pages.routes.ts:
Containing all /app
subroutes that are accessible only if the user is logged in. This is achieved using AuthGuardService.canActivateChild
:
export const pageRoutes: Routes = [
{
path: 'app',
component: PagesComponent,
canActivateChild: [AuthGuardService],
children: [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: HomePageComponent },
{ path: 'contents', component: ContentsComponent },
]
}
];
export const Routing: ModuleWithProviders = RouterModule.forChild(pageRoutes);
With the latter that redirects to /login
if the user isn't logged in. It's defined as:
canActivateChild(): boolean {
if (this._authService.isAuthenticated()) {
return true;
}
this._router.navigate(['login']);
return false;
}
When I navigate from
app/home
toapp/contents
it only goes toContentsComponent
after navigating two times. So, if I do two timesthis._router.navigate(['app/components']);
it works, if I do it only one time, the route changes fromapp/home
toapp/route
for 1ms and it returns toapp/home
, while if I do it a second time it changes route. While, if I'm inapp/contents
and try to navigate toapp/home
it changes route just fine.
isAuthenticated
works fine. Both authguards work just fine, so, if I try to access any app
child route when I'm not logged In I get redirected to login and If I try to access login
when I'm logged In I get redirected to app/home
.
I managed to debug a bit and I noticed the following flow:
app/home
-> app/contents
:
navigate(['app/contents'])
is calledPreventLoggedInAccess.canActivate
is calledAuthGuardService.canActivateChild
is calledapp/home
-> app/contents
:
navigate(['app/contents'])
is calledAuthGuardService.canActivateChild
is calledOf course the expected behavior is the second one.
EDIT
Removing this._router.navigate([/app/home]);
from PreventLoggedInAccess.canActivate
solves the issue
canActivate(): boolean {
if (!this._authService.isAuthenticated()) {
return true;
}
return false;
}
But still, I do not understand why PreventLoggedInAccess.canActivate
is called when navigating to an app
child even though AuthGuardService.canActivateChild
is attached to it? Why is it called only on the first attempt?
This route guard is used to keep the user from navigating away from a specific route. This guard can be useful when you want to prevent a user from accidentally navigating away without saving or some other undone tasks.
CanActivatelinkInterface that a class can implement to be a guard deciding if a route can be activated. If all guards return true , navigation continues. If any guard returns false , navigation is cancelled.
Angular route guards are interfaces provided by Angular which, when implemented, allow us to control the accessibility of a route based on conditions provided in class implementation of that interface. Here are some types of Angular guards: CanActivate, CanActivateChild, CanLoad, CanDeactivate and Resolve.
You have mentioned pageRoute can have all subchild of app so its routing file should contain that module.
So that concept of lazy loading and guards can be properly used. I have answered this by assuming that your pageRoute module is child of App.
I suggest to use the AuthGuard only one time. AuthGaurd should be used on module containing other modules or components and not be on login component itself.
Here page module is lazy loaded and can be activated only if authguard returns true In case of false user will navigated to login.
app.route.ts
const routes: Routes = [
{
path: '',
loadChildren: './pages/pages.module#PagesModule',
canActivate: [AuthGuardService]
},
{ path: 'login', loadChildren: './login/login.module#LoginModule' },
];
AuthGuard
canActivateChild(): boolean {
if (this._authService.isAuthenticated()) {
return true;
}
this._router.navigate(['/login']);
return false;
}
Page.route.ts
const routes: Routes = [
{
path: '', component: PageComponent,
children: [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: HomePageComponent },
{ path: 'contents', component: ContentsComponent },
]
}
];
In case you want to debug in current routing condition you can use Augury from the Chrome web store.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With