1


I have searched the internet and could not find an answer. I found this post on the route guard not working on browser refresh, and the solutions did not work because I think it was Firebase-specific.

app.module.ts

@NgModule({
  declarations: [
    AppComponent,
    HeaderComponent
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    HttpModule,
    MaterialModule,

    HomeModule,
    LoginModule,
    SettingsModule,

    RoutingModule
  ],
  exports: [
    RoutingModule
  ],
  providers: [
    AuthGuardService,
    AuthService,
    /* other services */
  ],
  bootstrap: [AppComponent],
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule { }


I have various routes defined in various routing modules:

app-routing.module.ts (global route config)

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

const routes: Routes = [
  // Default route
  {
    path: '**',
    redirectTo: '',
    pathMatch: 'full'
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class RoutingModule {}

login-routing.module.ts

const routes: Routes = [
  // Login
  {
    path: '',
    component: LoginComponent
   }
];

home-routing.module.ts

const routes: Routes = [
  // Home
  {
    path: 'home',
    component: HomeComponent,
    canActivate: [AuthGuardService],
    canActivateChild: [AuthGuardService]
  }
];

settings-routing.module.ts

const routes: Routes = [
  // Settings
  {
    path: 'settings',
    component: SettingsComponent,
    canActivate: [AuthGuardService]
  }
];


Below is the Auth Guard I use, which was modified from this article about logging in with jwt:

import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, CanLoad, Route } from '@angular/router';
import { AuthService } from '../services';
import { JwtHelper } from 'angular2-jwt';

@Injectable()
export class AuthGuardService implements CanActivate {
  private jwtHelper: JwtHelper = new JwtHelper();

  constructor(
    private authService: AuthService,
    private router: Router
  ) { }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    return this.navigateToLogin();
  }

  canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    return this.navigateToLogin();
  }

  private navigateToLogin(): boolean {
    if (localStorage.getItem('token')) {
      // if logged in & token not expired, return true
      if(!this.jwtHelper.isTokenExpired(localStorage.getItem('token'))) {
        return true;
      }
      // if token expired, logout 
      else {
        this.authService.logout();
      }
    }

    // re route to login
    this.router.navigate(['']);
    return false;
  }
}


With this current implementation, here is the behavior:

If user is not logged in

  • Going to / works
  • Going to /home or /settings in the URL redirects to / (login screen)
  • Going to any random URL (like /fjdsakfjkla) redirects to / (login screen)

If user is logged in

  • Typing /home or /settings in the URL directs user to correct route
  • Going to any random URL (like /fjdsakfjkla) redirects to /home
  • Type / (login page) directs user to /home


The problem is, when logged in, during a browser refresh, you are redirected to /home. How do I make it so if the user is logged in, a browser refresh will persist the route? For example, if I was on /settings, a browser refresh would NOT re-route to /home and stay on /settings.

Currently: /settings → browser refresh → /home
Desired: /settings → browser refresh → /settings

Prita Hasjim
  • 343
  • 1
  • 5
  • 15
  • I think that problem could be with order of routes definitions. Route with path "**" should be defined as last one. – Bartek Cichocki Sep 20 '17 at 19:49
  • Hey @BartekCichocki, I'm not sure what you mean by that. I looked at my code again and noticed I actually forgot to include the login-routing.module.ts, so I included that above. – Prita Hasjim Sep 20 '17 at 20:11
  • Can you show the global route config? You should have line similiar to "RouterModule.forRoot(routes)". What do you pass there? Basically there in "routes" variable path "**" should be the last one. – Bartek Cichocki Sep 20 '17 at 20:46
  • @BartekCichocki The global route config is app-routing.module.ts (updated in the post). The other route modules (login-routing, home-routing, settings-routing) all have `RouterModule.forChild(routes)` – Prita Hasjim Sep 20 '17 at 20:59
  • Ok, the last thing - could you show imports in app.module.ts? I mean @NgModule({ imports: [ ... – Bartek Cichocki Sep 20 '17 at 21:12
  • @BartekCichocki updated! Thanks for all of the help – Prita Hasjim Sep 20 '17 at 21:24
  • Nah, that is not what I supposed. Route order is Ok (RoutingModule is imported as last one). But I'm curious what is it. Can you share whole code so I can run it locally and check it? – Bartek Cichocki Sep 20 '17 at 21:43
  • Wait I think I see it. Please try to change order of LoginModule and SettingsModule in imports. The other way is to add pathMatch: 'full' in login-routing.module.ts – Bartek Cichocki Sep 20 '17 at 21:48
  • Thanks for helping though! I will try to get a fiddle working if others are stuck because a lot of what I shared on here was already condensed. – Prita Hasjim Sep 20 '17 at 21:49
  • No that didn't do it :( but what does `pathMatch` even do? – Prita Hasjim Sep 20 '17 at 21:52
  • For me it looks that on site refresh router hits Login page because it has path '' and default pathMatch is 'prefix' (it means that it will hit every route which starts with defined path - and every path starts with empty string). PathMatch full means that it will only hit when your url is really empty. – Bartek Cichocki Sep 20 '17 at 21:58

0 Answers0