3

I am trying to build a login page where the login template is replaced with the app+router-outlet.

The HTML:

<div class="contentWrapper" *ngIf="!logedin">
    Login html....
</div>

<div *ngIf="logedin">
    <div #header></div>
    <div class="contentWrapper">
        <div #nav></div>
        <div class="main">
            <router-outlet>
            </router-outlet>
        </div>
    </div>
</div>

The Component

export class AppComponent implements OnInit{
logedin = 0;

constructor(
    private _dcl:DynamicComponentLoader,
    private _elmRef:ElementRef,
    private _httpRest:HttpRest //http calls service
){}

ngOnInit(){}
login(){
    var vm = this;

    //simulated XHR
    setTimeout(()=>{
        vm.postLoginSuccess()
    })
}
postLoginSuccess(){
    var vm = this;
    vm.logedin =  1;
    setTimeout(()=>{
        vm.loadApp()
    },0);
}
loadApp(){
    this._dcl.loadIntoLocation(Header,this._elmRef,"header");
    this._dcl.loadIntoLocation(Navigation,this._elmRef,"nav");
}
}

I am trying to: 1) show a login template 2) on login success update logedin 3) hide login accordingly 4) show app

This results in an error msg:

Could not find variable header

I understand this is happening because the #header is a local variable under the scope of the *ngIf template. I tried to resolve this technique (swaping template using *ngIf and local variables # than using loadIntoLocation) in several ways without success.

The thing is my app frame (meaning navigation + header) is not loaded via the <router-outlet> so i need a conditional way to load the frame components without using routing (since <router-outlet> only renders content in my case), after login returned succesfully.

Help will be much appriciated.

wagwanJahMan
  • 203
  • 2
  • 9

2 Answers2

3

When the template variable is inside an *ngIf it isn't found. I don't know if this is by design or a bug. This is by design.

update Angular 2 dynamic tabs with user-click chosen components shows the same example with up-to-date code.

original (outdated code)

If you need to use DynamicComponentLoader you can do using a wrapper component like

import {Component, DynamicComponentLoader, ElementRef, Input, ViewChild, ViewContainerRef} from 'angular2/core';
@Component({
  selector: 'dcl-wrapper',
  template: `<div #target></div>`
})
export class DclWrapper {
  @ViewChild('target', {read: ViewContainerRef}) target;

  constructor(private dcl:DynamicComponentLoader) {}
  @Input() type;

  ngOnChanges() {
    if(this.cmpRef) {
      this.cmpRef.dispose();
    }
    if(this.type) {
      this.dcl.loadNextToLocation(this.type, this.target).then((cmpRef) => {
        this.cmpRef = cmpRef;
      });
    }
  }
}
@Component({
  selector: 'header-comp',
  template: 'header'
})
export class Header{}

@Component({
    selector: 'my-app',
    directives: [DclWrapper],
    template: `
    <h1>Hello</h1>
<div class="contentWrapper" *ngIf="!logedin">
    Login html....
</div>

<div *ngIf="logedin">
    <dcl-wrapper [type]="headerCmp"></dcl-wrapper>
    <div class="contentWrapper">
        <div #nav></div>
        <div class="main">
            <router-outlet>
            </router-outlet>
        </div>
    </div>
</div>   

<button (click)="login()">log in</button>
    `,
})
export class AppComponent {
  constructor(
    private _dcl:DynamicComponentLoader,
    private _elmRef:ElementRef,
    /*private _httpRest:HttpRest*/ /*http calls service*/){}

  headerCmp = null;
  logedin = true;
  ngOnInit(){}

  login(e){
    console.log('login');
    //var vm = this;

    //simulated XHR
    setTimeout(()=>{
        this.postLoginSuccess()
    })
  }

  postLoginSuccess(){
    //var vm = this;
    this.logedin =  true;
    setTimeout(()=>{
        this.loadApp();
    });
  }

  loadApp(){
    console.log('loadApp');
    this.headerCmp = Header;
    //this._dcl.loadIntoLocation(Header,this._elmRef,"header");
    //this._dcl.loadIntoLocation(Navigation,this._elmRef,"nav");
  }
}

Plunker example beta.17
Plunker example <= beta.15

Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
0

I resolved this issue using Michael D advice of using the [hidden] html5 attribute. I was not aware of the hidden html5 attr.

Changed html from:

<div class="contentWrapper" *ngIf="!logedin">
</div>
<div *ngIf="logedin">
<div #header></div>
<div class="contentWrapper">
    <div #nav></div>
    <div class="main">
        <router-outlet>
        </router-outlet>
    </div>
</div>

To:

<div class="contentWrapper" [hidden]="logedin"></div>
<div [hidden]="!logedin">
<div #header></div>
<div class="contentWrapper">
    <div #nav></div>
    <div class="main">
        <router-outlet>
        </router-outlet>
    </div>
</div>

wagwanJahMan
  • 203
  • 2
  • 9