0

Using angular 9 and angular router.

I tried to follow the following thread : Angular 2 different components with same route

What I would like to achieve is to have 2 route '', one that move to privateModule if authenticated, and publicModule if not.

so basically,

if I am authenticated and go to www.myApp.com <= PrivateModule if I am not authenticated and go to www.myApp.com <= PublicModule.

I setup a app-routing.module.ts =>

const routes: Routes = [
  {
    matcher: publicMatcher,
    loadChildren: publicModule,
  },
  {
    matcher: privateMatcher,
    loadChildren: privateModule,
    canActivate: [AuthPrivateGuard],
    canActivateChild: [AuthPrivateGuard],
  },
]

then I have 2 matchers, and I do not know exactly how to set them up. since the url is '' there is nothing to consume and I currently have a infinite loop.

export function privateMatcher(segments: UrlSegment[]): UrlMatchResult {
  const key = localStorage.getItem('auth')
  if (key && JSON.parse(key).accessToken) {
    console.log('private')
    return { consumed: segments }
  }
  return null
}



export function publicMatcher(segments: UrlSegment[]): UrlMatchResult {
  const key = localStorage.getItem('auth')
  if (!key || !JSON.parse(key)?.accessToken) {
    console.log({ consumed: segments })
    return { consumed: segments }
  }
  return null
}

I am probably using them wrong, or is not the good way to achieve what I want ?

Bobby
  • 4,372
  • 8
  • 47
  • 103

1 Answers1

1

We can achieve the same with this approach

  • Considering I want to route to http://localhost:4200/home, Create a home module with private, public modules, define route path to this common module in app-routing as below.

app-routing.module.ts

const routes: Routes = [
 
    {
      path: 'home',
      loadChildren: () => import('./modules/home/home.module').then(mod => 
      mod.HomeModule)
    },
    ...
  ];

home.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule, ROUTES, Routes } from '@angular/router';
import { AuthService } from '../services/auth.service';
@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    RouterModule
  ],
  providers:[
    {provide:ROUTES,
    useFactory: configHomeRoutes,
  deps: [AuthService],
    multi: true}
  ]
})
export class HomeModule { }

export function configHomeRoutes(authService: AuthService){
  let routes: Routes = [];
  if (authService.isAuthorized()) {
    routes = [
      {
        path: '', loadChildren: () => import('../private/private.module').then(mod => 
        mod.PrivateModule)
      }
    ];
  } else {
    routes = [
      {
        path: '', loadChildren: () => import('../public/public.module').then(mod => 
        mod.PublicModule)
      }
    ];
  }
  return routes;
}

private.module.ts

@NgModule({
  declarations: [PrivateComponent],
  imports: [
    CommonModule,
    RouterModule.forChild([{path: '', component: PrivateComponent}])
  ]
})
export class PrivateModule { }

public.module.ts

@NgModule({
  declarations: [PublicComponent],
  imports: [
    CommonModule,
    RouterModule.forChild([{path: '', component: PublicComponent}])
  ]
})
export class PublicModule { }
  • The method homeRoutes used by the useFactory provider in the homeModule is only executed the first time we navigate to the /home path, which causes to load the module loaded first time. To overcome this bug, we have to delete the /home path in the Router and add it again as shown below

auth.service.ts

  public isAuthorized(): boolean {
    return this.authorizedSource.value;
  }

  public setAuthorized(value: boolean): void {
    const previous = this.authorizedSource.value;
    this.authorizedSource.next(value);
    if (previous === this.authorizedSource.value) {
      return;
    }
    const i = this.router.config.findIndex(x => x.path === 'home');
    this.router.config.splice(i, 1);
    this.router.config.push(
      {path: 'home', loadChildren: () => import('../../modules/home/home.module').then(mod => mod.homeModule)}
    );
  }
Pallavi
  • 496
  • 5
  • 12
  • Hello, I looked at the medium link, and your answer, and managed to make something that is working even if not perfectly clean. Still, this answer the question, thanks – Bobby Jun 24 '20 at 06:30
  • Great! medium link is indeed helpful – Pallavi Jun 24 '20 at 07:55