Angular2 @Input do właściwości z get / set

178

Mam składnik Angular2 w tym komponencie, który obecnie ma kilka pól, które mają zastosowane przed nimi @Input (), aby umożliwić powiązanie z tą właściwością, tj.

@Input() allowDay: boolean;

To, co chciałbym zrobić, to w rzeczywistości powiązać się z właściwością za pomocą get / set, abym mógł wykonać inną logikę w seterze, coś takiego jak poniżej

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

jak bym to zrobił w Angular2?

Opierając się na sugestii Thierry'ego Templiera, zmieniłem to na, ale powoduje to błąd Nie można powiązać z „allowDay”, ponieważ nie jest to znana własność natywna:

//@Input() allowDay: boolean;
_allowDay: boolean;
get allowDay(): boolean {
    return this._allowDay;
}
@Input('allowDay') set allowDay(value: boolean) {
    this._allowDay = value;
    this.updatePeriodTypes();
}
Paul Cavacas
źródło
Jak i gdzie połączyć się z [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
Byłbym ciekawy, jak skonfigurować test jednostkowy, gdybyś poszedł drogą korzystania z get set, jak pokazano w zaakceptowanej odpowiedzi.
Winnemucca
1
Cokolwiek skończysz, upewnij się, że umieścisz punkt przerwania, instrukcję debugowania lub licznik wewnątrz settera, aby upewnić się, że zadziała tylko raz zgodnie z oczekiwaniami. Właśnie odkryłem, że mój jest aktualizowany przy każdym uruchomieniu wykrywania zmian, co powoduje straszną wydajność i dziwaczne zachowanie.
Simon_Weaver,

Odpowiedzi:

271

Możesz ustawić @Input bezpośrednio na seterze, jak opisano poniżej:

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

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

Zobacz ten plunkr: https://plnkr.co/edit/6miSutgTe9sfEMCb8N4p?p=preview .

Thierry Templier
źródło
1
Pojawia się następujący błąd Nie można powiązać z „allowDay”, ponieważ nie jest to znana własność natywna. Zobacz zaktualizowane pytanie, aby dokładnie dowiedzieć się, na co zmieniłem kod
Paul Cavacas
Jesteś pewny? Mi to pasuje. Dodałem plunkr. Być może zapomniałeś dodać dyrektywę do directivesatrybutu komponentu, w którym chcesz jej użyć ... Zaktualizowałem moją odpowiedź.
Thierry Templier
2
To zły pomysł, ponieważ jeśli używasz setera, ngOnChanges nie będzie uruchamiany.
user2867288
11
UWAGA : Obiekt setterbędzie nie być wywołane przez mutacje do wartości, które są przekazywane przez referencję (tzn naciska na tablicy, mutującymi obiekt itp.) Trzeba by wymienić całą wartość jest przekazywana jako Inputdla setterna spuście ponownie.
Nickofthyme
61

Jeśli jesteś zainteresowany głównie implementacją logiki tylko do ustawiacza :

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

Importowanie SimpleChangesnie jest potrzebne, jeśli nie ma znaczenia, która właściwość wejściowa została zmieniona lub jeśli masz tylko jedną właściwość wejściową.

Angular Doc: OnChanges

Inaczej:

private _allowDay: boolean;

@Input() set allowDay(value: boolean) {
  this._allowDay = value;
  this.updatePeriodTypes();
}
get allowDay(): boolean {
  // other logic
  return this._allowDay;
}
Martin Schneider
źródło
Ciekawe, czy jest jakaś korzyść z używania ngOnChanges w porównaniu z nieużywaniem właściwości set, jeśli interesuje Cię tylko logika ustawiająca?
Mese
4
Nie ma różnicy w "używaniu ngOnChanges a nieużywaniu set" ...;) Żartowanie na bok: Jedną z korzyści jest to, że twój komponent ma wiele @Inputwłaściwości i chcesz wywołać procedurę, gdy któraś z nich ulegnie zmianie. Tak więc potrzeba mniej kodu.
Martin Schneider
Ups, miał literówkę hehe. Ale ok, pomyślałem, że może to mieć większe znaczenie. Dzięki za odpowiedź :)
Mese
1
@ MA-Maddin Przypuszczam, że możesz również ustawić zdemontowane obserwowalne, jeśli spodziewasz się wielu zmian w tym samym czasie, z których każda wymagałaby uruchomienia procedury.
Simon_Weaver
Podejście ngOnChanges jest świetne !! Dobra odpowiedź. Jeśli ustawiana wartość nie może być prywatna, np. Jest używana jako powiązanie w szablonie, Konwencja ustawiająca / prywatna nazwa_właściwości staje się niespójna. ngOnChanges radzi sobie z tym doskonale
Drenai
8

@Paul Cavacas, miałem ten sam problem i rozwiązałem go ustawiając Input()dekorator nad getter.

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

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

Zobacz ten plunker: https://plnkr.co/edit/6miSutgTe9sfEMCb8N4p?p=preview

maxi-code
źródło
6
Ten błąd doprowadził mnie do szału, w końcu odkryłem, że powinieneś najpierw zdefiniować Input () (getter lub setter, ale dekorator wejścia musi iść pierwszy)
maxi-code
1
Oto inne odniesienie, które może pomóc https://github.com/angular/angular/issues/5477
maxi-code