Angular2 @ Вхід у властивість із get / set


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 я змінив його, але це призводить до помилки Не можу прив’язати до 'enableDay', оскільки це не відома рідна властивість:

//@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 (...) `.
Günter Zöchbauer

Мені було б цікаво побачити, як ви налаштували свій тест на одиницю, якби ви пройшли маршрут використання get set, як показано у прийнятій відповіді.
Віннемукка

1
Що б ви в кінцевому підсумку не зробили, не забудьте поставити точку перерви або налагодження, або лічильник всередині вашого сетера, щоб переконатися, що він запускається лише один раз, як очікувалося. Щойно я виявив, що мій оновлюється для кожного запуску виявлення змін, що спричиняє жахливу ефективність та химерну поведінку.
Simon_Weaver

Відповіді:


271

Ви можете встановити @ Input на сетері безпосередньо, як описано нижче:

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

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

Дивіться цей плагін: https://plnkr.co/edit/6miSutgTe9sfEMCb8N4p?p=preview .


1
Я отримую таку помилку Не можу прив’язати до 'enableDay', оскільки це не відома рідна властивість. Дивіться оновлене запитання, на що саме я змінив код
Пол Кавакас

Ти впевнений? Це працює для мене. Я додав plunkr. Можливо, ви забули додати директиву в directivesатрибут компонента, де ви хочете її використовувати ... Я оновив свою відповідь.
Тіррі Темплієр

2
Це погана ідея, оскільки якщо ви використовуєте сетер, ngOnChanges не спрацьовує.
користувач2867288


11
ПОПЕРЕДЖЕННЯ : setterбуде НЕ бути викликані мутаціями в значення , які передаються по посиланню (тобто штовхають на масив, що змінює об'єкт і т.д.). Ви повинні були б замінити всі значення передається як Inputдля setterзнову тригера.
Нікофтім

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 не потрібен, якщо не має значення, яке властивість введення було змінено або якщо у вас є лише одна властивість введення.

Кутовий документ: OnChanges

інакше:

private _allowDay: boolean;

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

Цікаво, чи є якась користь від використання ngOnChanges vs не використання властивості set, якщо вас цікавить лише логіка встановлення?
Месе

4
Немає різниці в тому, що "використовувати ngOnChanges vs не використовувати набір" ...;) Жарт убік: Однією перевагою є те, якщо ваш компонент має декілька @Inputвластивостей, і ви хочете викликати процедуру, коли будь-яка з них змінилася. Так потрібно менше коду.
Мартін Шнайдер

Упс, мав друкарську помилку. Але гаразд, думав, що це може мати більше значення. Дякую за відповідь tho :)
Mese

1
@ MA-Maddin Я вважаю, що ви також можете встановити дебютовану спостережувану станцію, якщо ви очікували декількох змін одночасно, що спричинило б за собою рутину, яку потрібно запустити.
Simon_Weaver

Підхід ngOnChanges чудовий !! Хороша відповідь. Якщо встановлене значення не може бути приватним, наприклад, воно використовується як прив'язка в шаблоні, умовниця _propertyName / приватне іменування стає непослідовною. ngOnChanges обійде це ідеально
Дренай

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 () (getter або setter, але декоратор введення повинен піти першим)
maxi-код

1
Ось інша довідка, яка може допомогти https://github.com/angular/angular/isissue/5477
maxi-код

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.