Search code examples
angularangular-routing

Angular router calls canActivate of element 1 even if router navigates to unguarded element 2


I have two components : HomeComponent which is guarded by AuthGuard, and LoginComponentwhich doesn't have any guard on it.

When I call logout() from HomeComponent, I destroy the token from localStorage and call this.router.navigate(['/login']). This redirects me to LoginComponent just for a split second; and then my application acts as if I tried to call HomeComponent directly and thereby calling the canActivate() function again, which leads to full reload of the application.

Here are portions of my code:

Logout function

   logout() {
        // remove user from local storage to log user out
        localStorage.removeItem('currentUser');
        this.router.navigate(['/login']);
        this.currentUserSubject.next(null);
    }

app.routing.ts

    { path: 'login', component: LoginComponent },
    { path: '', component: HomeComponent, canActivate: [AuthGuard] },

My AuthGuard's canActivate()

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
        const currentUser = this.authenticationService.currentUserValue;
        if (currentUser) {
            // authorised so return true
            return true;
        }

        // not logged in so redirect to login page with the return url
        this.router.navigate(['/login'], { queryParams: { returnUrl: state.url }});
        return false;
    }

I expect that the application doesn't get reloaded and it just goes to /login. How can I achieve this?

EDIT 1 I tried creating a mini version of my app in stackblitz here. I am a newbie to Angular, hence I had little problem recreating the issue there. After clicking the login button in the demo,a localStorage item is created but router is not navigating to /. I request you to kindly remove the /login... part from browser URL and hit enter to reload the page. You will the see how the app behaves. Try logging out and see the issue.


Solution

  • The reloading happens because you're using

    <a href="" ...>
    

    to logout. This tells the browser to navigate to the current URL (i.e. reload the page).

    You should use a button, and not a link. If you use a link, at least prevent the default action of the link:

    (click)="logout($event)"
    
    logout(event: Event) {
        // ...
        event.preventDefault();
    }
    

    Demo