Search code examples
angularangular-routerangular-router-guardsangular-route-guards

In Angular, is it possible to load different modules depending upon whether the user is authenticated or not?


For example, the URL: www.example.com should load one module if the user is authenticated, else it should load a different module.

I have tried using guards, but it didn't work as I expect it to.

I am pretty new to Angular. It would be much appreciated if someone could write a sample routes array for demonstration. :)

If the user is not authenticated, I want my routes to work something like below:

  {
    path: '',
    loadChildren: './home/home.module#HomeModule'
  },
  {
    path: 'login',
    loadChildren: './login/login.module#LoginModule'
  },
  {
    path: 'register',
    loadChildren: './register/register.module#RegisterModule'
  }

Else, if the user is authenticated, I want my routes to work something like below:

  {
    path: '',
    pathMatch: 'full',
    redirectTo: '/dashboard'
  },
  {
    path: 'dashboard',
    loadChildren: './dashboard/dashboard.module#DashboardModule'
  },
  {
    path: 'profile',
    loadChildren: './user-profile/user-profile.module#UserProfileModule'
  }

Solution

  • Yes, you can achieve this using the CanActivate guard (checking route access).

    CanActivate Checks to see if a user can visit a route.

    Having said that I would expect you to redirect to a different route after guardCheck.

    You should not have the router configuration to accommodate two different components or modules on same route. You can add them as child of a route and decide routing if you need them on same route.

    Update:

    I came across the concept of matcher which can be used to load two different routes at same path:

    const routes: Routes = [{
      path: 'list',
      matcher: matcherForAuthenticatedRoute,
      loadChildren: './user/register#RegisterModule'
    },
    {
      path: 'list',
      matcher: matcherForTheOtherRoute,
      loadChildren: './user/home#HomeModule'
    }]
    

    Now our matching logic depends on two functions, that can be as below:

    export function matcherForAuthenticatedRoute(
     segments: UrlSegment[],
     group: UrlSegmentGroup,
     route: Route) {
      const userService =  appInjector.get(MyService);
      const isPathMatch = segments[0].path === route.path;
      const isUserAuthenticated = userService.isUserAuthenticated('userId');      
      if(isPathMatch && isUserTypeMatch) { 
        return {consumed: [segments[0]]};
      } else {
        return null;
      }
    }
    

    We can define appInjector after bootstraping the app and export it to be used:

    appInjector = componentRef.injector;