角4指令显示@input值未定义

Akh*_*mar 0 directive typescript angular2-directives angular

我是angular指令的新手,所以我创建了如下指令:

import { Directive, ElementRef, Input, Output } from '@angular/core';

@Directive({
  selector: "[bonusCard]"
})
export class BonusCard {
  @Input() bonus: string;
  @Input() amount: string;
  @Input() isSeleted: string;
  constructor(private el: ElementRef){
    el.nativeElement.innerHTML = this.getTemplate()
  }

  getTemplate(){
    return ''+
      '<div>'+
        '<div class="bonus">'+this.bonus+'</div>'+
        '<div class="amount">'+this.amount+'</div>'+
        '<div class="radio '+(this.isSeleted?'is_seleted':'')+'"></div>'+
      '</div>' +
      '';
  }
}
Run Code Online (Sandbox Code Playgroud)

我在模板中使用此指令,如下所示:

  <div class="column col-3" *ngFor="let b of bonusJson;let i = index" bonusCard [bonus]="b.bonus" [amount]="b.amount" [isSeleted]="i==activeBonus"></div>
Run Code Online (Sandbox Code Playgroud)

其中变量定义如下:

bonusJson = [{
    bonus:1500,
    amount:2000
  },{
    bonus:1000,
    amount:1000
  },{
    bonus:500,
    amount:500
  },{
    bonus:0,
    amount:100
  }];
  activeBonus = 0;
Run Code Online (Sandbox Code Playgroud)

但是视图显示不正确undefind,如下所示。

$在此处输入图片说明

Cri*_*ìna 7

TL; DR

不要@Input()构造函数中使用属性的值。使用ngOninit()代替。


长答案

您正在构造函数中执行代码,但是构造函数是在Input绑定s 之前执行的。

当您引导应用程序时,Angular会使用new每个组件的按键创建一个组件树,从而执行它们的构造函数。但是在此阶段,变化检测周期尚未激活,该树还没有附加到DOM,并且大多数应用程序数据仍未获取和解析。

正如您可以从Angular团队的开发人员编写的本指南中阅读的那样,构造函数不是放置复杂的初始化逻辑的理想场所。您在构造函数中所需要做的只是基本的初始化和依赖项注入结果。

ngOnInit()挂钩方法会改变事情。当Angular调用此方法时,它已经将每个组件附加到DOM,注入了所有必需的依赖项并处理了输入绑定。您可以放心使用Input()财产。


具体答案

回到你的问题,你可以调用getTemplate()它查找this.bonusthis.amountthis.isSelected而父组件的观点是不是还解析和输入proprierites不是照样约束,所以您收到undefined代替。

为避免此问题,请将代码从构造函数移至ngOnInit挂钩。

export class BonusCard implements OnInit {
  @Input() bonus: string;
  @Input() amount: string;
  @Input() isSeleted: string;

  constructor(private el: ElementRef) {}

  ngOnInit() {
    this.el.nativeElement.innerHTML = this.getTemplate()
  }
Run Code Online (Sandbox Code Playgroud)

最后三点笔记

我想提供另外三个建议来改进您的代码:

  • 使用DomSanitizer在组件内部绑定HTML,您可以在此处阅读更多内容。
  • 使用模板字符串,您可以使用它用反引号(`)替换引号,这样您就可以在多行上编写模板
  • =====如果您确定要比较两个相同类型的变量(例如本例),则可以使用代替

所以:

[isSeleted]="i===activeBonus"
Run Code Online (Sandbox Code Playgroud)

return `<div>
          <div class="bonus"> ${this.bonus} </div>
          <div class="amount"> ${this.amount} </div>
          <div class="radio ${this.isSeleted?'is_seleted':''}"></div>
        </div>`;
Run Code Online (Sandbox Code Playgroud)