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

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 .


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

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


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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.