Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing router-outlet with *ngIf in app.component.html in angular2

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>
like image 898
Optimizal Avatar asked Oct 17 '16 01:10

Optimizal


People also ask

Can we use ngIf in router outlet?

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.

Can there be more than one router outlet element in Angular application?

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.

How do I use the router outlet in Angular 13?

Router-outlet in Angular works as a placeholder which is used to load the different components dynamically based on the activated component or current route state. Navigation can be done using router-outlet directive and the activated component will take place inside the router-outlet to load its content.

Can I use multiple router outlets in Angular 8?

Yes! We can use multiple router-outlets in same template by configuring our routers and simply add the router-outlet name. You can see in the example.


3 Answers

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-outletto 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="logedIn-route" *ngIf="routerActive">
<ng-container *ngTemplateOutlet="template"></ng-container>
</div>

<!--This is where my after login router stays-->
<div class="logedout-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/

like image 73
imal hasaranga perera Avatar answered Oct 11 '22 09:10

imal hasaranga perera


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.

like image 32
Edmar Miyake Avatar answered Oct 11 '22 09:10

Edmar Miyake


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)
like image 2
Nate May Avatar answered Oct 11 '22 11:10

Nate May