Angular2 @输入到具有get / set的属性


178

我在该组件中有一个Angular2组件,它目前有一堆字段,在它们之前应用了@Input()以允许绑定到该属性,即

@Input() allowDay: boolean;

我想做的实际上是使用get / set绑定到属性,以便可以在setter中执行其他一些逻辑,如下所示

_allowDay: boolean;
get allowDay(): boolean {
    return this._allowDay;
}
set allowDay(value: boolean) {
     this._allowDay = value;
     this.updatePeriodTypes();
}

我将如何在Angular2中做到这一点?

基于Thierry Templier的建议,我将其更改为,但这引发错误无法绑定到“ allowDay”,因为它不是已知的本机属性:

//@Input() allowDay: boolean;
_allowDay: boolean;
get allowDay(): boolean {
    return this._allowDay;
}
@Input('allowDay') set allowDay(value: boolean) {
    this._allowDay = value;
    this.updatePeriodTypes();
}

如何以及在何处绑定到[allowDay]="....". If the field (setter) name and the property name you want to use for binding are the same, you can omit the parameter for @Input(...)`。
君特Zöchbauer

我很想知道如果您按照接受的答案所示使用get set的方法,如何设置单元测试。
Winnemucca

1
无论您最终要做什么,请确保在设置器中放置一个断点,调试语句或计数器,以确保它仅按预期触发一次。我只是发现我的每次变更检测运行都在进行更新,这导致了糟糕的性能和古怪的行为。
Simon_Weaver

Answers:


271

您可以直接在设置器上设置@Input,如下所述:

_allowDay: boolean;
get allowDay(): boolean {
    return this._allowDay;
}

@Input('allowDay')
set allowDay(value: boolean) {
    this._allowDay = value;
    this.updatePeriodTypes();
}

请参阅以下代码:https ://plnkr.co/edit/6miSutgTe9sfEMCb8N4p ? p = preview 。


1
我收到以下错误无法绑定到“ allowDay”,因为它不是已知的本机属性。请参阅更新的问题,以获取我将代码更改为的确切信息
Paul Cavacas

你确定吗?这个对我有用。我加了一个朋克。也许您忘记了将该指令添加到directives要使用它的组件的属性中...我更新了答案。
Thierry Templier

2
这是一个坏主意,因为如果您使用设置器,则ngOnChanges不会触发。
user2867288 '18


11
警告:该setterNOT通过突变值,其通过引用传递(即推到一个数组,突变的对象,等)来触发。您需要替换作为传递的整个值Inputsetter以便再次触发。
Nickofthyme

61

如果您仅对仅对设置程序执行逻辑感兴趣:

import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';

// [...]

export class MyClass implements OnChanges {
  @Input() allowDay: boolean;

  ngOnChanges(changes: SimpleChanges): void {
    if(changes['allowDay']) {
      this.updatePeriodTypes();
    }
  }
}

SimpleChanges如果更改了哪个输入属性无关紧要,或者只有一个输入属性,则不需要导入。

Angular Doc:OnChanges

除此以外:

private _allowDay: boolean;

@Input() set allowDay(value: boolean) {
  this._allowDay = value;
  this.updatePeriodTypes();
}
get allowDay(): boolean {
  // other logic
  return this._allowDay;
}

只是好奇,如果您只对setter逻辑感兴趣,那么使用ngOnChanges和不使用set属性有什么好处吗?
Mese

4
开玩笑:“好处是,如果您的组件具有多个@Input属性,并且您想在例程中的任何一个发生更改时调用例程,那么使用ngOnChanges与不使用set并没有什么区别。”;因此所需的代码更少。
Martin Schneider

跌宕起伏,打错了呵呵。但是好吧,以为它可能更有意义。谢谢您的回答:)
Mese

1
@ MA-Maddin我想如果您希望同时进行多项更改,并且每次都会导致需要运行一个例程,那么您还可以设置一个防抖动的可观察值。
Simon_Weaver

ngOnChanges方法很棒!好答案。如果所设置的值不能是私有的,例如在模板中用作绑定,则_propertyName setter / private命名约定会变得不一致。ngOnChanges完美解决了这个问题
Drenai

8

@Paul Cavacas,我​​遇到了同样的问题,我通过将Input()装饰器设置在吸气剂上方来解决了。

  @Input('allowDays')
  get in(): any {
    return this._allowDays;
  }

  //@Input('allowDays')
  // not working
  set in(val) {
    console.log('allowDays = '+val);
    this._allowDays = val;
  }

看到这个矮人:https ://plnkr.co/edit/6miSutgTe9sfEMCb8N4p ? p = preview


6
这个错误让我抓狂,我终于发现您应该首先定义Input()(getter或setter,但必须首先输入输入装饰器)
maxi-code

1
这是可能对您有所帮助的其他参考https://github.com/angular/angular/issues/5477
maxi-code

1

在此处更新了关于stackblitz上的angular 7.0.1的可接受答案:https ://stackblitz.com/edit/angular-inputsetter ? embed =1& file = src/app/app.component.ts

directives在组件装饰器选项中不再可用。因此,我为应用程序模块提供了子指令。

谢谢@ thierry-templier

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.