Angular2 @Input ke properti dengan get / set

178

Saya memiliki komponen Angular2 di komponen yang saat ini memiliki banyak bidang yang memiliki @Input () diterapkan sebelum mereka untuk memungkinkan pengikatan ke properti itu, yaitu

@Input() allowDay: boolean;

Apa yang ingin saya lakukan sebenarnya adalah mengikat ke properti dengan get / set, sehingga saya bisa melakukan beberapa logika lain di setter, sesuatu seperti berikut

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

bagaimana saya melakukan ini di Angular2?

Berdasarkan saran Thierry Templier, saya mengubahnya, tetapi itu melempar kesalahan Tidak dapat mengikat ke 'allowDay' karena itu bukan properti asli yang dikenal:

//@Input() allowDay: boolean;
_allowDay: boolean;
get allowDay(): boolean {
    return this._allowDay;
}
@Input('allowDay') set allowDay(value: boolean) {
    this._allowDay = value;
    this.updatePeriodTypes();
}
Paul Cavacas
sumber
Bagaimana dan di mana Anda mengikat [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 (...) `.
Günter Zöchbauer
Saya akan penasaran untuk melihat bagaimana Anda mengatur unit test Anda jika Anda menempuh rute menggunakan set sebagaimana ditunjukkan dalam jawaban yang diterima.
Winnemucca
1
Apa pun yang Anda lakukan akhirnya pastikan untuk meletakkan breakpoint, atau pernyataan debug, atau counter di dalam setter Anda untuk memastikan itu hanya menembak sekali seperti yang diharapkan. Saya baru saja menemukan bahwa milik saya sedang diperbarui untuk setiap menjalankan deteksi perubahan yang menyebabkan kinerja mengerikan dan perilaku aneh.
Simon_Weaver

Jawaban:

271

Anda bisa mengatur @Input pada setter secara langsung, seperti dijelaskan di bawah ini:

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

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

Lihat plunkr ini: https://plnkr.co/edit/6miSutgTe9sfEMCb8N4p?p=preview .

Thierry Templier
sumber
1
Saya mendapatkan kesalahan berikut Tidak dapat mengikat ke 'allowDay' karena ini bukan properti asli yang dikenal. Lihat pertanyaan yang diperbarui untuk mengetahui persis apa yang saya ubah kodenya
Paul Cavacas
Apakah kamu yakin Ini bekerja untuk saya. Saya menambahkan plunkr. Mungkin Anda lupa menambahkan arahan ke directivesatribut komponen tempat Anda ingin menggunakannya ... Saya memperbarui jawaban saya.
Thierry Templier
2
Ini adalah ide yang buruk karena jika Anda menggunakan setter, ngOnChanges tidak menyala.
user2867288
11
PERINGATAN : The setterakan tidak dipicu oleh mutasi pada nilai-nilai yang dikirimkan dengan referensi (yaitu mendorong ke array, bermutasi objek, dll). Anda perlu mengganti seluruh nilai yang diteruskan sebagai Inputuntuk settermemicu lagi.
Nickofthyme
61

Jika Anda terutama tertarik untuk mengimplementasikan logika ke setter saja :

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

Impor SimpleChangestidak diperlukan jika tidak masalah properti input mana yang diubah atau jika Anda hanya memiliki satu properti input.

Doc Sudut: OnChanges

jika tidak:

private _allowDay: boolean;

@Input() set allowDay(value: boolean) {
  this._allowDay = value;
  this.updatePeriodTypes();
}
get allowDay(): boolean {
  // other logic
  return this._allowDay;
}
Martin Schneider
sumber
Hanya ingin tahu, apakah ada manfaat untuk menggunakan ngOnChanges vs tidak menggunakan properti set jika Anda hanya tertarik pada logika setter?
Mese
4
Tidak ada perbedaan dalam "menggunakan ngOnChanges vs tidak menggunakan set" ...;) Mengesampingkan: Salah satu manfaatnya adalah, jika komponen Anda memiliki beberapa @Inputproperti dan Anda ingin memanggil rutin ketika salah satu dari mereka telah berubah. Jadi lebih sedikit kode yang dibutuhkan.
Martin Schneider
Ups, punya salah ketik hehe. Tapi ok, pikir itu mungkin lebih relevan. Terima kasih atas jawabannya :)
Mese
1
@ MA-Maddin Saya kira Anda juga bisa mengatur debounce diamati jika Anda mengharapkan beberapa perubahan semua pada saat yang sama yang masing-masing akan menghasilkan rutin yang perlu dijalankan.
Simon_Weaver
Pendekatan ngOnChanges luar biasa !! Jawaban yang bagus. Jika nilai yang disetel tidak boleh pribadi, misalnya digunakan sebagai pengikatan dalam templat, konvensi _propertyName / konvensi penamaan pribadi menjadi tidak konsisten. ngOnChanges menyiasati ini dengan sempurna
Drenai
8

@ Paul Cavacas, saya memiliki masalah yang sama dan saya menyelesaikannya dengan mengatur Input()dekorator di atas pengambil.

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

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

Lihat penjungkal ini: https://plnkr.co/edit/6miSutgTe9sfEMCb8N4p?p=preview

kode maks
sumber
6
Bug ini membuat saya gila, saya akhirnya menemukan bahwa Anda harus mendefinisikan Input () terlebih dahulu (pengambil atau penyetel tetapi dekorator input harus pergi dulu)
maxi-code
1
Berikut referensi lain yang dapat membantu https://github.com/angular/angular/issues/5477
maxi-code