Search code examples
angularangular2-routingnested-routesrouter-outlet

Using nested router-outlets in angular 4


Im using multiple router-oulets to load my components. The outer router-outlet is used load most basic components like login, home, 404. I used nested router-outlet to load sub components of home page. That router-outlet is nested inside the home.component.

home.component.html

<app-header></app-header>
<router-outlet name="homeRoute"></router-outlet>
<app-footer></app-footer> 

app.module.ts

const appRoutes: Routes = [
  {path: '', component: HomeComponent, children: [
    {path: '', component: DashboardComponent, outlet: 'homeRouter'},
    {path: 'user', component: UserComponent, outlet: 'homeRouter'},
    {path: 'user/:id', component: UserdetailComponent, outlet: 'homeRouter'}
  ]},
  {path: 'login', component: LoginformComponent},
  {path: '**', component: NotfoundComponent}
];

HomeComponent and LoginformComponent need to loaded from the outer router-outlet. Home component contains inner router-outlet with name 'homeRouter', which I want to use to load sub components of the home page. But navigation of inner router wont work. I tried to access each component using router.navigate() method and using URL. But both of them did not work as expected.

Can someone tell me what is wrong with this code. I examined and tried few previous questions about the same problem but none worked fine.

Here are the URLs i tried for different components

  1. http://localhost:4200 dashboardComponet (this one works)
  2. http://localhost:4200/user userComponent (doesnt work. routes to notFoundComponent)
  3. http://localhost:4200/user/U001 userDetailComponent (doenst work.still route to notFoundComponent)

Solution

  • you do not need named router-outlet for nesetd routes, you can remove outlet: 'homeRouter' from the Routes and name="homeRoute" from router-outlet and it should work.

    Having said that, if you have requirement for multiple router-outlet so that you can load an auxilary route along with primary route, the name of router-oulet should be same as outlet property. in the Routes which you are using you have outlet: "homeRouter" and name="homeRoute", they should be same.

    Here is a complete example with multi level nested routes,

    Plunker

    import { Component, NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import { ActivatedRoute, RouterModule, Routes } from '@angular/router';
    
    @Component({
        selector: 'my-app',
        template: `<h1>Hello</h1>
      <a routerLink="/" >Home</a>
       <a routerLink="/admin" >Admin</a>
        <a routerLink="/nonexistingroute" >Non existing Route</a>
      <hr />
      <router-outlet></router-outlet>
      `
    })
    export class AppComponent {
    }
    
    @Component({
        template: `<h1>Home</h1>
       <a routerLink="/" >Dashboard</a>
        <a routerLink="/users" >Users</a>
      <hr />
       <router-outlet></router-outlet>
      `
    })
    export class HomeComponent { }
    
    @Component({
        template: `<h1>Admin</h1>
      `
    })
    export class AdminComponent { }
    
    @Component({
        template: `<h1>Dashboard</h1>
      `
    })
    export class DashboardComponent { }
    
    @Component({
        template: `<h1>Users</h1>
      <a routerLink="user/1" >User 1</a>
      <a routerLink="user/2" >User 2</a>
      <hr />
       <router-outlet></router-outlet>
      `
    })
    export class Users { }
    
    @Component({
        template: `<h1>User {{id}}</h1>
      `
    })
    export class UserdetailComponent {
        id = '';
        constructor(private readonly route: ActivatedRoute) {
            this.route.params.subscribe(params => {
                this.id = params.id;
            });
        }
    }
    
    @Component({
        template: `<h1>Not found</h1>
      `
    })
    export class NotfoundComponent { }
    
    const appRoutes: Routes = [
        {
            path: '',
            component: HomeComponent,
            children: [
                { path: '', component: DashboardComponent },
                {
                    path: 'users', component: Users,
                    children: [
                        { path: 'user/:id', component: UserdetailComponent }
                    ]
                }
            ]
        },
        {
            path: 'admin',
            component: AdminComponent
        },
        { path: '**', component: NotfoundComponent }
    ];
    
    @NgModule({
        imports: [BrowserModule, RouterModule.forRoot(appRoutes)],
        declarations: [AppComponent, HomeComponent, AdminComponent, NotfoundComponent, DashboardComponent, Users, UserdetailComponent],
        bootstrap: [AppComponent]
    })
    
    export class AppModule { }