Skip to content

Is there a way I can render a 2 level nested component in Angular using `router-outlet`?

I have a sidebar with some links. The sidebar is located at the /dashboard route. The links on the sidebar are direct children to /dashboard. I now want to render the children of /dashboard inside the main router-outlet. I have no idea on how to approach this. The following are some code snippets to elaborate my question further

My routing structure

const routes: Routes = [
  {
    path: '',
    component: LoginComponent,
  },
  {
    path: 'dashboard',
    component: DashboardComponent,
    children: [
      {
        path: 'roles',
        component: RolesComponent,
      },
      {
        path: 'workgroups',
        component: WorkgroupsComponent,
        children: [
          {
            path: 'savewg',
            component: WgDetailsComponent,
          },
        ]
      },
      {
        path: 'users',
        component: UsersComponent,
      },
    ],
  },
];

App component

<!-- Main app component -->
<div class="app-view">
 <router-outlet></router-outlet>
</div>

Login.html

<button mat-raised-button color="warn" class="login-field" (click)="login(email, password)"
            <!-- rest of code ommited for brevity  -->

Login.ts

public login(email: string, password: string) {
    this.router.navigate(['dashboard'], { replaceUrl: true });
  }

Workgroup Component html

    <button mat-raised-button color="warn" [routerLink]="['savewg']">
            <mat-icon>add</mat-icon>
              New
        </button>
       <!-- Code ommited for brevity -->

<router-outlet></router-outlet>
<div class="workgroup-filters">
<mat-form-field appearance="outline">
    <!-- rest of Code ommited for brevity -->
  • When I click on the new button in the workgroup component, I want it to navigate me to the savewg component view and replace the content in the workgroup component.
  • Any suggestions on how I can tackle this will be appreciated

Answer

Modules are only allow one main router-outlet per module. You will have to create a separate module for workgroups path and lazy load it. The workgroups module will have its own routing file and its own router outlet where you will load all your routes from your workgroup module. See below stackblitz for a working example.

app-routing.module.ts

const routes: Routes = [
  ...
  {
    path: 'workgroups',
    loadChildren: () => import('./workgroups/workgroups.module').then(m => m.WorkgroupsModule)
  },
  ...
];

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

workgroups-routing.module.ts

const routes: Routes = [
  {
    path: '',
    component: WorkgroupsComponent,
    children: [
      {
        path: 'savewg',
        component: WgDetailsComponent
      },
      {
        path: '**',
        redirectTo: 'savewg',
        pathMatch: 'full'
      }
    ]
  },
  
];

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

workgroups.module.ts

@NgModule({
  imports: [
    CommonModule,
    WorkgroupsRoutingModule
  ],
  declarations: [
    WorkgroupsComponent, 
    WgDetailsComponent
    ]
})
export class WorkgroupsModule { }

Below are resources for lazy loading modules and a stackblitz example.

https://stackblitz.com/edit/angular-ivy-hbogtn

https://www.freakyjolly.com/angular-nested-routing-with-multiple-routeroutlet-using-loadchildren-having-own-router-modules-example-application/#.X3IQa3WYXmE