0

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.

DilumN
  • 2,889
  • 6
  • 30
  • 44
AngularM
  • 15,982
  • 28
  • 94
  • 169

2 Answers2

1

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.

Michael Oryl
  • 20,856
  • 14
  • 77
  • 117
  • With the current setup the header flickers when the Boolean changes – AngularM Dec 17 '15 at 14:12
  • Oh, in that case the system I proposed with routes would work. You'd be switching views. I should mention a few things, though: You appear to be working with an old Angular 2 build. View is now gone - templates are stored in the Component decorator. Angular 2 went into beta a day and a half ago, so the API should be pretty much static. You should be using that going forward to ensure your app will function in the future. – Michael Oryl Dec 17 '15 at 14:18
  • What's the npm to update to the latest angular? Eg the npm command for git bash – AngularM Dec 17 '15 at 14:22
  • Change the version mentioned in your package.json and do a regular 'npm install'. Pay attention to the fact that some dependencies are no longer included, too: http://stackoverflow.com/questions/34318885/how-to-load-rxjs-and-zone-js-reflect-metadata-with-angular-2-beta – Michael Oryl Dec 17 '15 at 14:48
  • Just to add to what Michael is saying, when Angular reads app.ts it only runs once to figure out what html to display which then loads your header component. As to the flicker, you have the hidden attribute which I'm guessing is causing the delay.. I wouldn't do the routing, conditional loading should work... – Dennis Smolek Dec 17 '15 at 17:42
  • Oh yeah, I didn't notice the [hidden] there. I'd stick with what you have and remove that to see how it goes, @AngularM. – Michael Oryl Dec 17 '15 at 18:27
  • So remove the hidden and use ng if? – AngularM Dec 17 '15 at 21:29
  • @AngularM Yes. Just remove the [hidden] attributes and see if that gets rid of the flicker. Leave the *ngIf as you have them. – Michael Oryl Dec 17 '15 at 23:37
  • @AngularM Did removing the [hidden] attributes fix the flicker problem? – Michael Oryl Dec 24 '15 at 18:51
0

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

Ashwini Jindal
  • 811
  • 8
  • 15