I have an Angular2 application with one router outlet that displays different components depending on which link is clicked in a side menu.
The markup for the main component containing the <router-outlet>
looks like this
<div *ngIf="authenticated == false"> <app-login></app-login> </div> <div *ngIf="authenticated"> <div class="page home-page"> <header class="header"> <app-navbar></app-navbar> </header> <div class="page-content d-flex align-items-stretch"> <div class="sidebar-container"> <app-sidebar-menu></app-sidebar-menu> </div> <div class="content-inner"> <app-page-header></app-page-header> <div id="sub-content"> <router-outlet></router-outlet> </div> <app-footer></app-footer> </div> </div> </div> </div>
If I click the Demo link, the demo component is rendered, but if I then click the Home link, the home component is rendered above the demo component in DOM. Clicking them a few times will result with a DOM like this
<div _ngcontent-c0="" id="sub-content"> <router-outlet _ngcontent-c0=""></router-outlet> <app-home _nghost-c6="">...</app-home> <app-demo _nghost-c7="">...</app-demo> <app-home _nghost-c6="">...</app-home> <!-- Why so many here? Should be just either one <app-home> or <app-demo> --> <app-demo _nghost-c7="">...</app-demo> <app-home _nghost-c6="">...</app-home> <app-demo _nghost-c7="">...</app-demo> <app-footer _ngcontent-c0="" _nghost-c5="">...</app-footer> </div>
The routes are defined as
export const router: Routes = [ { path: 'demo', component: DemoComponent, canActivate: [AuthGuard] }, { path: 'home', component: HomeComponent, canActivate: [AuthGuard] } ]
How come that the <router-outlet>
doesn't replace the component, but instead adds another "instance" of the component when switching between the routes?
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.
Import RouterModule from @angular/router link Routing lets you display specific views of your application depending on the URL path. To add this functionality to your sample application, you need to update the app.module.ts file to use the module, RouterModule . You import this module from @angular/router .
Run ng generate to create the application routing module. Puts the file in src/app instead of its own directory. Tells ng generate to register it in the imports array of the AppModule . First, the app-routing.module.ts file imports RouterModule and Routes so the application can have routing capability.
Angular Router supports multiple outlets in the same application. A component has one associated primary route and can have auxiliary routes. Auxiliary routes enable developers to navigate multiple routes at the same time.
By using the method of elimination, I found out that the culprit of the issue was the BrowserAnimations
module in my app.module.ts
. By removing it from my imports
it the problem went away. I'll look into creating a Plunker to demonstrate it.
Update: This is described in this Github issue.
Update 2017-12-13: This has now been fixed with this PR, fix(animations): properly recover and cleanup DOM when CD failures occur.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With