简体   繁体   中英

Angular 2 - I have 3 headers components. Hows best to toggle these 2 headers?

Angular 2 - When a user logs into my website I want to change the header. I have 2 headers components. Hows best to do this?

Currently I have 3 headers and I use "ng-if" in the app.ts template and toggle based off a variable.

This approach currently works however, I hits the app.ts file 3 times because of this.

I'm using angular2 and typescript.

The goal is to have the header change on login as one user type and then if I login as another user type the other header shows. Theres also an external header (3 im toggling in total in the app.ts file).

I basically dont want the app.ts file to get hit 3 times.

This is my code for the app.ts for the top part:

 @Component({
     selector: 'app',
     providers: [UserService, UserProfile]
 })

 @View({
     template: `
         <HeaderNavigation *ng-if="!isLoggedIn" [hidden]="!isPageLoadReady"></HeaderNavigation>     
        <HeaderNavigationLoggedIn *ng-if="isLoggedIn && !isCompanyLogin" [hidden]="!isPageLoadReady"></HeaderNavigationLoggedIn>
         <HeaderNavigationLoggedInCompany *ng-if="isLoggedIn && isCompanyLogin" [hidden]="!isPageLoadReady"></HeaderNavigationLoggedInCompany>

         <div class="content">
             <router-outlet></router-outlet>    
         </div>
     `,
     directives: [RouterOutlet, RouterLink, HeaderNavigation,      HeaderNavigationLoggedIn, HeaderNavigationLoggedInCompany, NgIf]
 })

 @RouteConfig([
     { path: '/', redirectTo: '/login' },
     { path: '/login', component: Login, as: 'Login' }, 
     { path: '/dashboard', component: Dashboard, as: 'Dashboard' }
 ])

*Notice the 3 headers where ones called: "HeaderNavigationLoggedIn"

Thank you.

I don't understand what you mean by "it hits the app.ts three times because of this". As I see your code, you just display a different header based on which boolean expression shows as true.

You could, of course', use ngSwitch instead, but that is basically the same thing as using three ngIf directives.

You page doesn't get called three times because of the ngIfs in it - it is loaded once and the DOM is dynamically changed based on the conditions.

If you wanted to get fancy, I suppose you could use routes to specify which header is displayed. You would define routes on your main component for the three cases:

@RouteConfig([
    {path: '/notloggedin', name: 'NotLoggedIn', component: NotLoggedInHeaderComponent, useAsDefault: true},
    {path: '/loggedin', name: 'LoggedIn', component: LoggedInHeaderComponent},
    {path: '/loggedincompany', name: 'LoggedInCompany', component: LoggedInCompanyComponent}
])

Then you would build three header components, each of which includes possibly the same child component for the main content, or contains differing components to change the user experience based upon needs.

A new RouteConfig decorator on those header components could then duplicate the same routes for the rest of the app, perhaps.

I'm not sure if this is what you are looking for, since I don't really see a problem with the current system as you explained it. But this system might be more modular.

Update:

As was pointed out by @DennisSmolek, you are probably running into problems due to the use of the [hidden] attributes in your header code. Remove those and see if that fixes the flicker problem.

by subscribe to the one variable change ,we can subscribe a event to update as required.

below example can help you more:

Firstly, create a service that will be responsible for sharing the route names between components. And create a new Subject "subjects work as an Observable and Observer at the same time"

import {Injectable} from 'angular2/core';
import {Subject} from 'rxjs/Rx';

@Injectable()
export class RouteNames{
  public name = new Subject();
}

Secondly, provide your service at the application level by injecting it on bootstrap:

import {RouteNames} from './route-names.service';
bootstrap(AppComponent, [ROUTER_PROVIDERS,RouteNames]);

Now, all you need to do is inject your service into app.component and into every component that will change the route name.

app.component: subscribe to RouteNames.name subject and update the variable routeName on next.

import {RouteNames} from './route-names.service';
@Component({
  selector: 'my-app',
  template: `
    <h1 class="title">{{routeName}}</h1>
    <nav>
      <a [routerLink]="['CrisisCenter']">Crisis Center</a>
      <a [routerLink]="['Heroes']">Heroes</a>
    </nav>
    <router-outlet></router-outlet>
  `,
   ...
})
@RouteConfig([
   ...
])
export class AppComponent {
  routeName = "Component Router";
  constructor(private _routeNames:RouteNames){
    this._routeNames.name.subscribe(n => this.routeName = n);
  }
}

Now, on CrisisCenter, Inject the RouteNames service and call next on RouteNames.name:

import {RouteNames} from '../route-names.service';

@Component({
  ...
})
@RouteConfig([
  ...
])
export class CrisisCenterComponent {
  constructor(private _routeNames:RouteNames){
    _routeNames.name.next('Crisis Center');
  }
}

And that is it, Here is working plunker

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM