Angular2 @Input su una proprietà con get / set


178

Ho un componente Angular2 in quel componente che attualmente ha un sacco di campi che hanno @Input () applicato prima di loro per consentire l'associazione a quella proprietà, cioè

@Input() allowDay: boolean;

Quello che vorrei fare è in realtà unire una proprietà con get / set, in modo da poter fare qualche altra logica nel setter, qualcosa come il seguente

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

come lo farei in Angular2?

Sulla base del suggerimento di Thierry Templier, l'ho modificato in, ma questo genera l'errore Impossibile legare a 'allowDay' poiché non è una proprietà nativa nota:

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

Come e dove ti leghi a [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,

Sarei curioso di vedere come hai impostato il tuo test unitario se hai seguito il percorso di utilizzo get set come mostrato nella risposta accettata.
Winnemucca,

1
Qualunque cosa tu faccia, assicurati di inserire un breakpoint, un'istruzione di debug o un counter all'interno del tuo setter per assicurarti che stia sparando solo una volta come previsto. Ho appena scoperto che il mio veniva aggiornato per ogni corsa di rilevamento delle modifiche che causava prestazioni orribili e comportamenti bizzarri.
Simon_Weaver,

Risposte:


271

È possibile impostare direttamente @Input sul setter, come descritto di seguito:

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

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

Vedi questo plunkr: https://plnkr.co/edit/6miSutgTe9sfEMCb8N4p?p=preview .


1
Ottengo il seguente errore Impossibile associare 'allowDay' poiché non è una proprietà nativa nota. Vedi la domanda aggiornata per sapere esattamente in cosa ho cambiato il codice
Paul Cavacas,

Sei sicuro? Per me funziona. Ho aggiunto un plunkr. Forse hai dimenticato di aggiungere la direttiva directivesall'attributo del componente in cui desideri utilizzarlo ... Ho aggiornato la mia risposta.
Thierry Templier,

2
Questa è una cattiva idea perché se si utilizza il setter, ngOnChanges non si attiva.
user2867288


11
AVVISO : Il settersarà NON essere innescati da mutazioni ai valori che sono passati per riferimento (cioè spingono ad una matrice, mutanti un oggetto, ecc). Dovresti sostituire l'intero valore che viene passato come Inputper il settertrigger di nuovo.
Nickofthyme,

61

Se sei interessato principalmente all'implementazione della logica solo per il setter :

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

L'importazione di SimpleChangesnon è necessaria se non importa quale proprietà di input è stata modificata o se si dispone di una sola proprietà di input.

Documento angolare: OnChanges

altrimenti:

private _allowDay: boolean;

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

Solo curioso, c'è qualche vantaggio nell'usare ngOnChanges rispetto al non usare la proprietà set se sei interessato solo a una logica setter?
Mese il

4
Non c'è alcuna differenza tra "usare ngOnChanges e non usare set" ...;) Scherzi a parte: un vantaggio è se il componente ha più @Inputproprietà e si desidera chiamare una routine quando una di esse è cambiata. Quindi meno codice necessario.
Martin Schneider,

Ups, aveva un refuso hehe. Ma ok, ho pensato che potesse avere più rilevanza. Grazie per la risposta però :)
Mese il

1
@ MA-Maddin Suppongo che potresti anche impostare un osservabile rimbalzato se ti aspettassi più modifiche contemporaneamente che porterebbero ciascuna a una routine da eseguire.
Simon_Weaver,

L'approccio di ngOnChanges è fantastico !! Buona risposta. Se il valore impostato non può essere privato, ad es. Viene utilizzato come associazione nel modello, la convenzione setter / nome privato _propertyName diventa incoerente. ngOnChanges ci riesce perfettamente
Drenai

8

@Paul Cavacas, ho avuto lo stesso problema e ho risolto posizionando il Input()decoratore sopra il getter.

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

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

Vedi questo plunker: https://plnkr.co/edit/6miSutgTe9sfEMCb8N4p?p=preview


6
Questo bug mi ha fatto impazzire, ho finalmente scoperto che dovresti definire prima Input () (getter o setter ma il decoratore di input deve andare per primo)
maxi-code

1
Ecco altri riferimenti che potrebbero essere utili https://github.com/angular/angular/issues/5477
maxi-code

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.