Angular2 - Routing not working when using router-outlet name

12,370

The problem lies in how you are trying to access your pages.

Let's start with your routing configuration.

@NgModule({
  imports: [
    RouterModule.forChild([
      {
        path: 'admin',
        component: AdminComponent,
        children: [
          {
            path: '',
            redirectTo: 'dashboard1',
            pathMatch: 'full'
          },
          {
            path: 'dashboard1',
            component: AdminDashboard1Component,
            outlet:'one'
          },
          {
            path: 'dashboard2',
            component: AdminDashboard2Component,
            outlet:'one'
          }
        ]
      }
    ])
 ],it attempts to perform a 
  exports: [
    RouterModule
  ]
})
export class AdminRoutingModule { }

At face value, the configuration seems to be correct, however, it is not correct to the way you want to use it.

When the AdminRoutingModule is loaded lazily, the path admin is rendered in the context of a <router-outlet></router-outlet> that is found within some parent component, which for this example we'll call it BaseComponent whose content is

@Component({ template: '<router-outlet></router-outlet'})
export class BaseComponent {
}

and is tied to the following routing config (note that this is to explain what is happening).

@NgModule({
  imports: [
    RouterModule.forRoot([
      {
        path:'', component:BaseComponent,
        children: [
          { path:'a', loadChildren:'some-path/admin-routing.module#AdminRoutingModule // This will be loaded in the router-outlet found within the BaseComponent
        ]
      }
    ]), ...
 ],
 declerations: [...]
 bootstrap: [...]
})
export class AppModule { }

...Back to your routing config

RouterModule.forChild([
  {
    path: 'admin',
    component: AdminComponent,
    children: [
      {
        path: '', // Tied with the main router-outlet
        redirectTo: 'dashboard1',
        pathMatch: 'full'
      },
      {
        path: 'dashboard1', // Tied with a named outlet
        component: AdminDashboard1Component,
        outlet:'one'
      },
      {
        path: 'dashboard2', // Tied with a named outlet
        component: AdminDashboard2Component,
        outlet:'one'
      }
    ]
  }
])

Note that the above config ties the base path denoted with path: '' to a base outlet. On the other hand paths dashboard1 and dashboard2 are tied to another outlet, that is named outlet one.

Since the base path is tied to the base outlet, the redirect that is configured, ie, redirect to dashboard1, is attempted on the base outlet. Since, using the above configuration, no dashboard1 is configured with the base outlet, the redirection fails with the error specifying that no outlet exists with that url is (this is the correct behavior).

Simply put, you cannot redirect with the above config, from one router outlet, to a different one, because simply put, within the redirect there is nothing that specifies that it should be rendering to a different outlet. This is also why removing the outlet:'one' from your config would work, because redirecting would be happening in the same outlet tree.

Solution

You cannot perform a redirect like you are mentioning. However there are solutions to achieve what you want.

In your AdminComponent have both outlets present, as below

<!-- Content Wrapper. Contains page content -->
<router-outlet></router-outlet>
<router-outlet name="one"></router-outlet>

Add a component to your base path, which upon init, performs the navigation that you require like so...

In your routing config

{
    path: '', component: MyBaseAdminComponent
},

In your MyBaseAdminComponent

@Component({ template: '' })
export class MyBaseAdminComponent implements OnInit {
    constructor(private router:Router;) {}

    ngOnInit() {
       this.router.navigate([ { outlet: { one: [ 'dashboard1' ] } ]);
    }
}

The above should give you the solution you require.

Here's a working plunker to demonstrate the above behavior, and routing to auxiliary routes.

Share:
12,370
DarioN1
Author by

DarioN1

Updated on June 19, 2022

Comments

  • DarioN1
    DarioN1 almost 2 years

    I'm trying to give a name to the router-outlet but it is not working.

    This is the basic routing that works perfectly:

    routing module

    @NgModule({
      imports: [
        RouterModule.forChild([
          {
            path: 'admin',
            component: AdminComponent,
            children: [
              {
                path: '',
                redirectTo: 'dashboard1',
                pathMatch: 'full'
              },
              {
                path: 'dashboard1',
                component: AdminDashboard1Component
              },
              {
                path: 'dashboard2',
                component: AdminDashboard2Component
              }
            ]
          }
        ])
      ],
      exports: [
        RouterModule
      ]
    })
    export class AdminRoutingModule { }
    

    component html

    <div class="wrapper">
    
      <app-admin-header></app-admin-header>
      <!-- Left side column. contains the logo and sidebar -->
      <app-admin-left-side></app-admin-left-side>
    
      <!-- Content Wrapper. Contains page content -->
      <router-outlet></router-outlet>
    
      <!-- /.content-wrapper -->
      <app-admin-footer></app-admin-footer>
    
      <!-- Control Sidebar -->
      <app-admin-control-sidebar></app-admin-control-sidebar>
      <!-- /.control-sidebar -->
    </div>
    

    Now I want to give a name to the router-outlet in order to implement some customizations but it doesen't work.

    If I apply this changes:

     <router-outlet name='one'></router-outlet>
    

    and:

    imports: [
        RouterModule.forChild([
          {
            path: 'admin',
            component: AdminComponent,
            children: [
              {
                path: '',
                redirectTo: 'dashboard1',
                pathMatch: 'full'
              },
              {
                path: 'dashboard1',
                component: AdminDashboard1Component,
                outlet:'one'
              },
              {
                path: 'dashboard2',
                component: AdminDashboard2Component
                outlet:'one'
              }
            ]
          }
        ])
      ]
    

    The routing is not working:

    /admin : the application is loaded but noone component is injected

    /admin/dashboard1 : the application is not loaded and I get this error in console: Error: Cannot match any routes. URL Segment: 'admin/dashboard1'

    Thanks to support

    • Rahul Singh
      Rahul Singh over 6 years
      can you reproduce this in stackblitz or something
  • DarioN1
    DarioN1 over 6 years
    Fantastic explaination, what about to move all the routing ( that is simple ) inside the basic app-routing.module instead of manage it in the sublevel ?
  • JeanPaul A.
    JeanPaul A. over 6 years
    That could be another solution, however I tried to remain along the lines of what the OP requested. Could be that the module structure in the real application is working with lazy loading, which is very common in even small applications.