Search code examples
angularangular-routing

How can I create a custom redirector in Angular 10?


I'm using routing in my angular project for site navigation, however, I'd like to redirect the user from the root/host URL based on various conditions and I'm not sure this is possible with the Angular Router.

I have therefore attempted to make a HomeComponent to handle these redirects.

Here's a flowchart explaining what I'm trying to achieve: Root URL Flow

  • If the user is logged in, they should be taken to their respective portal - the user type is stored in the user's token
  • Users should only be able to access the portal they've been assigned to
  • The user shouldn't be able to access the login page if they're logged in

In my main app-routing module, I have this:

import { HomeComponent } from './../home/home.component';
import { LoginComponent } from './../login/login.component';
import { Routes, RouterModule, PreloadAllModules } from '@angular/router';
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

const appRoutes: Routes = [
  {
    path: 'login',
    component: LoginComponent
  },
  {
    path: 'staff',
    loadChildren: () => import('../staff-portal/staff-portal.module').then(m => m.StaffPortalModule)
  },
  {
    path: '**',
    component: HomeComponent
  },
];

@NgModule({
  imports: [
    CommonModule,
    RouterModule.forRoot(
      appRoutes,
      {
        preloadingStrategy: PreloadAllModules
      }
      )
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {

 }

My home (redirector) component:

import { AuthService } from './../_services/auth.service';
import { NavigationStart, Router } from '@angular/router';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-home',
  template: ''
})
export class HomeComponent {

  constructor(private authService: AuthService, private router: Router) { 
    if (this.authService.loggedIn)
        {
          let parsedToken = this.authService.getParsedToken();

          if (parsedToken.type === '0')
          {
            this.router.navigate(['/staff/home']);
            return;
          }
          else if (parsedToken.type === '1')
          {
            this.router.navigate(['/student/home']);
            return;
          }
          else if (parsedToken.type === '2')
          {
            this.router.navigate(['/parent/home']);
            return;
          }
        }

    this.router.navigate(['/login']);
    return;
   }

}

The issue I'm having at the moment is that when the user is not logged in and navigates to the root, angular attempts to display the HomeComponent's template (an empty string).

I'm not entirely sure using a component is the correct way of implementing this sort of behaviour, this is just what I've managed to come up with so far but please feel free to suggest an alternative.


Solution

  • I would suggest looking into Route guards to solve routing logic depending on authentication status.

    So instead of writing your redirection logic inside the component, you can instead keep it nice and tidy inside the guard class instead.

    Example of route config:

    {
      path: '/your-path',
      component: YourComponent,
      canActivate: [YourGuard],
    }
    

    Example of guard code:

    export class YourGuard implements CanActivate {
      canActivate(
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot): boolean {
          // your  logic goes here
      }
    }