101

Is it possible to have multiple router-outlet in the same template?

If yes then how to configure the routes?

I am using angular2 beta.

Rohit Sharma
  • 3,304
  • 2
  • 19
  • 34
Islam Shaheen
  • 1,239
  • 3
  • 11
  • 12
  • 1
    What do you exactly want to implement? Could sub routes fit your needs? See this link: https://angular.io/docs/ts/latest/guide/router.html#!#child-router. – Thierry Templier Jan 06 '16 at 09:07
  • i need to build an application that uses multiple session (tabs) each session has the same content (like the browser tabs). – Islam Shaheen Jan 06 '16 at 10:05
  • check the talk from the developer of the router, to see what is currently possible -> https://www.youtube.com/watch?v=z1NB-HG0ZH4 IF I remember well there are child routes and auxiliary routes. – Angular University Jan 06 '16 at 13:01

8 Answers8

66

yes you can, but you need to use aux routing. you will need to give a name to your router-outlet:

<router-outlet name="auxPathName"></router-outlet>

and setup your route config:

@RouteConfig([
  {path:'/', name: 'RetularPath', component: OneComponent, useAsDefault: true},
  {aux:'/auxRoute', name: 'AuxPath', component: SecondComponent}
])

Check out this example, and also this video.


Update for RC.5 Aux routes has changed a bit: in your router outlet use a name:

<router-outlet name="aux">

In your router config:

{path: '/auxRouter', component: secondComponentComponent, outlet: 'aux'}
Shayan Shafiq
  • 1,447
  • 5
  • 18
  • 25
Tomer Almog
  • 3,604
  • 3
  • 30
  • 36
  • 1
    by the way, as of January 2016, according to this resource we should not use aux just yet, since it is not ready https://github.com/angular/angular/issues/5027#issuecomment-169464546 – Tomer Almog Jan 08 '16 at 00:31
  • thanks for the reply, i am using angular2 beta. i tried to define the aux route : { aux: '/edit-entity/:id', name: 'EditEntity', component: EditEntityComponent } when i call it doesn't work: this._router.navigate(['/', ['EditEntity'], { id: id }]); – Islam Shaheen Jan 11 '16 at 12:24
  • make sure you are including the complete route in the navigate section, not relative to your component. – Tomer Almog Jan 11 '16 at 21:48
  • if you want a relative route use ['./routeToYourComponent'] notice the dot before the slash – Tomer Almog Apr 25 '16 at 17:00
  • 4
    Update: as of May 2016, Angular2 just released their RC (release candidate) and now Aux routes are supposed to work. – Tomer Almog May 09 '16 at 16:22
  • @TomerAlmog any idea as how they are supposed to work? Theres no 'aux' memeber on the configs routes (but theres an 'outlet') – BobbyTables Jun 22 '16 at 09:49
  • @zedd you need to use the new router bundle, not the router-deprecated to use aux – Tomer Almog Jun 22 '16 at 17:05
  • 3
    1 vote for update answer to RC5. Angular2 change so fast. – teddy Aug 31 '16 at 05:49
57

You can have multiple router-outlet in same template by configuring your router and providing name to your router-outlet, you can achieve this as follows.

Advantage of below approach is thats you can avoid dirty looking URL with it. eg: /home(aux:login) etc.

Assuming on load you are bootstraping appComponent.

app.component.html

<div class="layout">
    <div class="page-header">
        //first outlet to load required component
        <router-outlet name='child1'></router-outlet>
    </div>
    <div class="content">
        //second outlet to load required component
        <router-outlet name='child2'></router-outlet>
    </div>
</div>

Add following to your router.

{
    path: 'home',  // you can keep it empty if you do not want /home
    component: 'appComponent',
    children: [
        {
            path: '',
            component: childOneComponent,
            outlet: 'child1'
        },
        {
            path: '',
            component: childTwoComponent,
            outlet: 'child2'
        }
    ]
}

Now when /home is loaded appComponent will get load with allocated template, then angular router will check the route and load the children component in specified router outlet on the basis of name.

Like above you can configure your router to have multiple router-outlet in same route.

Reyan Chougle
  • 4,917
  • 2
  • 30
  • 57
jigar gala
  • 1,600
  • 12
  • 20
  • I tried your approach, but it does not work. – Filip Witkowski Dec 21 '20 at 09:27
  • @FilipWitkowski you really need to pay attention to the routes, you must have the children's path as an empty string i.e. "" otherwise the router will need you to provide which outlet you want to target (or nothing will work) – Flavien Volken Nov 30 '22 at 14:13
19

Aux routes syntax has changed with the new RC.3 router.

There are some known issues with aux routes but basic support is available.

You can define routes to show components in a named <router-outlet>

Route config

{path: 'chat', component: ChatCmp, outlet: 'aux'}

Named router outlet

<router-outlet name="aux">

Navigate aux routes

this._router.navigateByUrl("/crisis-center(aux:chat;open=true)");

It seems navigating aux routes from routerLink is not yet supported

<a [routerLink]="'/team/3(aux:/chat;open=true)'">Test</a>

<a [routerLink]="['/team/3', {outlets: {aux: 'chat'}}]">c</a>

Not tried myself yet

See also Angular2 router in one component

RC.5 routerLink DSL (same as createUrlTree parameter) https://angular.io/docs/ts/latest/api/router/index/Router-class.html#!#createUrlTree-anchor

Shabbir Dhangot
  • 8,954
  • 10
  • 58
  • 80
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Is this supposed to work in RC5? I haven't managed to get it working. Looking at the source code for the router I cant find any "@Input() name" either. – Kungen Aug 25 '16 at 08:27
  • `@Input()` name is a property of the `RouterOutlet` class. I have to check the aux route path syntax for routerLink. – Günter Zöchbauer Aug 25 '16 at 08:29
  • The current syntax seems to be `c` – Günter Zöchbauer Aug 25 '16 at 08:38
  • Please look at this question and see if you manage to help me. http://stackoverflow.com/questions/39142396/angular-2-rc5-router-named-outlets – Kungen Aug 25 '16 at 10:12
  • @GünterZöchbauer After looking at your answer - I think i'm missing something - is it possible to remove AUX routes after visiting them via routerLink ? ( not via code ) . [_I've tried your answer in this simple plnkr without success. The aux route just won't reomove_](https://plnkr.co/edit/NaSnjDvXcW8zxpYuG04Y?p=preview) – Royi Namir May 09 '17 at 11:15
  • I never really tried aux routes because I always run into some bugs. I haven't tried since several months and many things were fixed since then, but I'm not familiar with aux routes and afraid I'm not able to help you. There might be other questions with answers to that problem. – Günter Zöchbauer May 09 '17 at 12:11
16

<a [routerLink]="[{ outlets: { list:['streams'], details:['parties'] } }]">Link</a>

<div id="list">
    <router-outlet name="list"></router-outlet>
</div>
<div id="details">
    <router-outlet name="details"></router-outlet>
</div>

`

 {
    path: 'admin',
    component: AdminLayoutComponent,
    children:[
      {
        path: '',
        component: AdminStreamsComponent, 
        outlet:'list'
      },
      {
        path: 'stream/:id',
        component: AdminStreamComponent,
        outlet:'details'
      }
    ]
  }
Tomiwa Adefokun
  • 287
  • 4
  • 7
3

Yes you can as said by @tomer above. i want to add some point to @tomer answer.

  • firstly you need to provide name to the router-outlet where you want to load the second routing view in your view. (aux routing angular2.)
  • In angular2 routing few important points are here.

    • path or aux (requires exactly one of these to give the path you have to show as the url).
    • component, loader, redirectTo (requires exactly one of these, which component you want to load on routing)
    • name or as (optional) (requires exactly one of these, the name which specify at the time of routerLink)
    • data (optional, whatever you want to send with the routing that you have to get using routerParams at the receiver end.)

for more info read out here and here.

import {RouteConfig, AuxRoute} from 'angular2/router';
@RouteConfig([
  new AuxRoute({path: '/home', component: HomeCmp})
])
class MyApp {}
Aniruddha Das
  • 20,520
  • 23
  • 96
  • 132
Pardeep Jain
  • 84,110
  • 37
  • 165
  • 215
2

You can not use multiple router outlets in the same template with ngIf condition. But you can use it in the way shown below:

<div *ngIf="loading">
  <span>loading true</span>
  <ng-container *ngTemplateOutlet="template"></ng-container>
</div>

<div *ngIf="!loading">
  <span>loading false</span>
  <ng-container *ngTemplateOutlet="template"></ng-container>
  </div>

  <ng-template #template>
    <router-outlet> </router-outlet>
  </ng-template>
dev0201
  • 73
  • 4
0

There seems to be another (rather hacky) way to reuse the router-outlet in one template. This answer is intendend for informational purposes only and the techniques used here should probably not be used in production.

https://stackblitz.com/edit/router-outlet-twice-with-events

The router-outlet is wrapped by an ng-template. The template is updated by listening to events of the router. On every event the template is swapped and re-swapped with an empty placeholder. Without this "swapping" the template would not be updated.

This most definetly is not a recommended approach though, since the whole swapping of two templates seems a bit hacky.

in the controller:

  ngOnInit() {
    this.router.events.subscribe((routerEvent: Event) => {
      console.log(routerEvent);
      this.myTemplateRef = this.trigger;
      setTimeout(() => {
        this.myTemplateRef = this.template;
      }, 0);
    });
  }

in the template:

<div class="would-be-visible-on-mobile-only">
  This would be the mobile-layout with a router-outlet (inside a template): 
  <br>
  <ng-container *ngTemplateOutlet="myTemplateRef"></ng-container>
</div>

<hr>

<div class="would-be-visible-on-desktop-only">
  This would be the desktop-layout with a router-outlet (inside a template): 
  <br>
  <ng-container *ngTemplateOutlet="myTemplateRef"></ng-container>
</div>

<ng-template #template>
    <br>
    This is my counter: {{counter}}
    inside the template, the router-outlet should follow
    <router-outlet>
    </router-outlet>
</ng-template>

<ng-template #trigger>
  template to trigger changes...
</ng-template>
Tobias Gassmann
  • 11,399
  • 15
  • 58
  • 92
-1

This worked for me and pretty straight-forward and simple.

<div *ngIf="authenticated">
  <ng-container *ngTemplateOutlet="template"></ng-container>
</div>

<div *ngIf="!authenticated">
  <ng-container *ngTemplateOutlet="template"></ng-container>
</div>

<ng-template #template>
  <router-outlet></router-outlet>
</ng-template>