Reputation: 256
I am using angular 2.0 final. I am trying to change the location of the router-outlet in the main app.component.html. The template is updating fine display wise except, the first time I use router.navigate the component won't display in the new router-outlet, and there is no error. The second and every time after I use router.navigate it works properly.
example template of app.component.html
<div *ngIf="authenticated() == false">
<h1>not logged in</h1>
<router-outlet>
</router-outlet>
</div>
<div *ngIf="authenticated()">
<h1>logged in</h1>
<router-outlet>
</router-outlet>
</div>
Upvotes: 23
Views: 23897
Reputation: 10029
I'd like to say please use a named router-outlet
which work perfectly fine, but issue for me is that such urls are not user friendly at all and I personally believe url with outlet name does not make sense,
ex:-
route
{ path : "forgotPassword", component :ForgotPassword , outlet : "notlogedin" }
output in browser address bar
http://localhost:4200/(notlogedin:forgotPassword)
see how stupid that it looks in the addressbar.
so if you try to use *ngIf
to conditionally disable and enable router-outlet
to overcome the problem it does not work. One router-outlet
will get registered and no matter what you do, next router-outlet
will not respond to the route changes.
So Here is The Solution
Using ngTemplateOutlet
and ng-template
we can provide a good solution to this problem by keeping only one router-outlet
see below sample code.
<ul>
<li><a routerLink="/login">login</a></li>
<li><a routerLink="/dashboard">dashboard</a></li>
</ul>
<!-- This is where my before login router stays -->
<div class="loggedIn-route" *ngIf="routerActive">
<ng-container *ngTemplateOutlet="template"></ng-container>
</div>
<!-- This is where my after login router stays -->
<div class="loggedout-route" *ngIf="!routerActive">
<ng-container *ngTemplateOutlet="template"></ng-container>
</div>
<ng-template #template>
<router-outlet></router-outlet>
</ng-template>
Try the fiddle
https://jsfiddle.net/imal/e4tyqv95/36/
Upvotes: 42
Reputation: 83
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>
Upvotes: 3
Reputation: 37
I've had the same problem wherein I have multiple <router-outlet>
in my app.component.html and expected them to be in/visible with *ngIf
. I've tried almost everything I can find online (some worked but breaks the principle of SPA of angular).
This totally worked for me, and I think is the most logical and pretty simple solution.
<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>
Upvotes: 1
Reputation: 1
User Routing like this, it will solve the problem for named outlet
{
path: 'login',
children: [
{
path: '',
component: LoginComponent,
outlet: 'loutlet',
}
]
},
{
path: 'profile',
component: ProfileComponent,
}
Upvotes: -1
Reputation: 4062
I had to use ViewContainerRef
so that both mobile and desktop would leverage the same router outlet:
<!-- MOBILE -->
<div *ngIf="isMobile">
<div #mobileOutlet></div>
</div>
<!-- DESKTOP -->
<div *ngIf="!isMobile">
<div #desktopOutlet></div>
</div>
<ng-template #tpl>
<router-outlet></router-outlet>
</ng-template>
And I had no problem using createEmbeddedView
for both:
@ViewChild('mobileOutlet', { read: ViewContainerRef }) _vcrMobile;
@ViewChild('desktopOutlet', { read: ViewContainerRef }) _vcrDesktop;
@ViewChild('tpl') tpl;
ngAfterViewInit() {
if (this.isMobile) this._vcrDesktop.createEmbeddedView(this.tpl);
else this._vcrMobile.createEmbeddedView(this.tpl);
}
only thing is that you'll have to toggle this outlet if you switch between breakpoints. For example, from desktop to mobile resize:
this._vcrDesktop.clear();
this._vcrMobile.createEmbeddedView(this.tpl)
Upvotes: 3
Reputation: 12390
You should consider using named router-outlet
, instead.
It states in the documentation: A template may hold exactly one unnamed .
<div *ngIf="authenticated() == false">
<h1>not logged in</h1>
<router-outlet name="notloggedin">
</router-outlet>
</div>
<div *ngIf="authenticated()">
<h1>logged in</h1>
<router-outlet name="loggedin">
</router-outlet>
</div>
The router will look like:
{ path: 'page1', component: Page1Component, outlet: 'notloggedin' },
{ path: 'page2', component: Page2Component, outlet: 'loggedin' }
Here an example from @yurzui in this post.
Upvotes: 11