Angular2 @ get / setを使用したプロパティへの@Input


178

私はそのコンポーネントにAngular2コンポーネントを持っていますが、それは現在そのプロパティへのバインドを可能にするためにそれらの前に@Input()が適用されているたくさんのフィールドを持っています、すなわち

@Input() allowDay: boolean;

私がやりたいのは、実際にはget / setを使用してプロパティにバインドすることです。これにより、次のような他のロジックをセッターで実行できます。

_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
最終的に何をするにせよ、ブレークポイント、デバッグステートメント、またはカウンターをセッター内に配置して、期待どおりに1回だけ発生することを確認してください。変更検出を実行するたびに私のものが更新され、ひどいパフォーマンスと風変わりな動作が発生していることがわかりました。
Simon_Weaver 2018

回答:


271

以下で説明するように、@ Inputをセッターに直接設定できます。

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

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

このplunkrを参照してください:https ://plnkr.co/edit/6miSutgTe9sfEMCb8N4p?p=preview 。


1
既知のネイティブプロパティではないため、「allowDay」にバインドできません。私がコードを何に変更したかについては、更新された質問を参照してください
Paul Cavacas

本気ですか?わたしにはできる。plunkrを追加しました。ディレクティブdirectivesを使用するコンポーネントの属性にディレクティブを追加するのを忘れたのかもしれません...私の回答を更新しました。
ティエリーテンプリエ2016

2
セッターを使用するとngOnChangesが起動しないため、これは悪い考えです。
user2867288 2018


11
警告setterNOT(即ちなど、アレイにプッシュオブジェクトを変異)参照によって渡される値に突然変異によってトリガされます。再度トリガーするInputために、渡される値全体を置き換える必要がありsetterます。
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変更された入力プロパティが重要でない場合、または入力プロパティが1つしかない場合は、のインポートは必要ありません。

Angular Doc:OnChanges

さもないと:

private _allowDay: boolean;

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

興味があるのは、セッターロジックのみに関心がある場合に、ngOnChangesを使用することと、setプロパティを使用しないことの利点はありますか?
Mese

4
「ngOnChangesを使用することとsetを使用しないこと」に違いはありません...;)冗談は別です:1つの利点は、コンポーネントに複数の@Inputプロパティがあり、それらのいずれかが変更されたときにルーチンを呼び出す場合です。したがって、必要なコードが少なくなります。
Martin Schneider

Ups、タイプミスがあった。しかし、わかりました。もっと関連性があるかもしれないと思いました。答えをありがとうtho :)
Mese

1
@ MA-Maddin複数の変更が同時に発生し、それぞれがルーチンの実行を必要とする場合は、デバウンスされたオブザーバブルを設定することもできると思います。
Simon_Weaver

ngOnChangesアプローチは素晴らしいです!! いい答えだ。設定される値が非公開にすることができない場合(例:テンプレートでバインディングとして使用される場合)、_ propertyNameセッター/非公開の命名規則は不整合になります。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()を最初に定義する必要があることが最終的にわかりました(ゲッターまたはセッターですが、入力デコレーターを最初に指定する必要があります)
maxi-code

1
ここでは役立つかもしれない他の参照ですhttps://github.com/angular/angular/issues/5477を
マキシコード

1

ここで、stackblitzのAngular 7.0.1に対する承認済みの回答を更新しました:https ://stackblitz.com/edit/angular-inputsetter?embed=1&file=src/app/app.component.ts

directivesコンポーネントデコレータオプションにはありません。そのため、アプリモジュールにサブディレクティブを提供しました。

ありがとう@ thierry-templier

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.