【问题标题】:Using *ngIf + template variables + loadIntoLocation to load components into view programatically使用 *ngIf + 模板变量 + loadIntoLocation 以编程方式将组件加载到视图中
【发布时间】:2016-08-11 07:32:34
【问题描述】:

我正在尝试构建一个登录页面,其中登录模板被替换为 app+router-outlet。

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>

组件

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");
}
}

我正在尝试: 1) 显示登录模板 2)登录成功更新登录 3)相应地隐藏登录 4) 显示应用程序

这会导致错误消息:

Could not find variable header

我知道这是因为 #header 是 *ngIf 模板范围内的局部变量。我尝试以多种方式解决此技术(使用 *ngIf 和局部变量 # 交换模板而不是使用 loadIntoLocation)但均未成功。

问题是我的应用程序框架(意味着导航+标题)不是通过 加载的,所以我需要一种有条件的方式来加载框架组件而不使用路由(因为 只在我的情况),登录成功后返回。

我们将非常感谢您的帮助。

【问题讨论】:

  • 注意:如果使用箭头函数,则不需要 var vm = this。
  • 您能否确认使用 [hidden] 而不是 ngIf 可以解决您的问题?
  • 我不明白你为什么要使用DynamicComponentLoader。为什么不创建一个Header 和一个Navigation 组件并将它们绑定在模板中。
  • 我同意 [hidden] 解决了问题!!!非常感谢 Michael D,我不知道 [hidden] html5 属性。

标签: javascript typescript angular angular2-routing angular2-template


【解决方案1】:

当模板变量在*ngIf 内时,找不到它。 我不知道这是设计使然还是错误。这是设计使然。

更新 Angular 2 dynamic tabs with user-click chosen components 使用最新代码显示相同的示例。

原始(过时的代码)

如果您需要使用DynamicComponentLoader,您可以使用类似的包装器组件

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

【讨论】:

    【解决方案2】:

    我使用 [hidden] html5 属性的 Michael D 建议解决了这个问题。我不知道隐藏的 html5 属性。

    将 html 更改为:

    <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>
    

    收件人:

    <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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多