Angular2 @Input cho một thuộc tính với get / set


178

Tôi có một thành phần Angular2 trong thành phần đó, hiện tại nó có một trường bó có @Input () được áp dụng trước chúng để cho phép liên kết với thuộc tính đó, tức là

@Input() allowDay: boolean;

Những gì tôi muốn làm là thực sự liên kết với một thuộc tính bằng get / set, để tôi có thể thực hiện một số logic khác trong setter, đại loại như sau

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

Làm thế nào tôi có thể làm điều này trong Angular2?

Dựa trên đề xuất của Thierry Templier, tôi đã thay đổi nó, nhưng điều đó gây ra lỗi Không thể liên kết với 'allowDay' vì đây không phải là một tài sản bản địa đã biết:

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

Làm thế nào và ở đâu để bạn liên kết với [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

Tôi sẽ tò mò muốn xem yo thiết lập bài kiểm tra đơn vị của bạn như thế nào nếu bạn đi theo lộ trình sử dụng get set như trong câu trả lời được chấp nhận.
Winnemucca

1
Bất cứ điều gì bạn kết thúc, hãy đảm bảo đặt một điểm dừng, hoặc câu lệnh gỡ lỗi hoặc bộ đếm bên trong bộ cài đặt của bạn để đảm bảo rằng nó chỉ bắn một lần như mong đợi. Tôi chỉ thấy cái của tôi đang được cập nhật cho mỗi lần phát hiện thay đổi gây ra hiệu suất khủng khiếp và hành vi kỳ quặc.
Simon_Weaver

Câu trả lời:


271

Bạn có thể đặt trực tiếp @Input trên setter, như được mô tả bên dưới:

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

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

Xem plunkr này: https://plnkr.co/edit/6miSutgTe9sfEMCb8N4p?p=preview .


1
Tôi nhận được lỗi sau Không thể liên kết với 'allowDay' vì đó không phải là thuộc tính gốc được biết đến. Xem câu hỏi cập nhật để biết chính xác những gì tôi đã thay đổi mã thành
Paul Cavacas

Bạn có chắc không? Nó làm việc cho tôi. Tôi đã thêm một plunkr. Có lẽ bạn đã quên thêm chỉ thị vào directivesthuộc tính của thành phần mà bạn muốn sử dụng nó ... Tôi đã cập nhật câu trả lời của mình.
Thierry Templier

2
Đây là một ý tưởng tồi vì nếu bạn sử dụng setter, ngOnChanges sẽ không kích hoạt.
dùng2867288


11
CẢNH BÁO : Ý setterchí KHÔNG được kích hoạt bởi các đột biến thành các giá trị được truyền bằng tham chiếu (nghĩa là đẩy vào một mảng, làm biến đổi một đối tượng, v.v.). Bạn sẽ cần phải thay thế toàn bộ giá trị được thông qua như một Inputcho setterđến kích hoạt một lần nữa.
Nickofthyme

61

Nếu bạn chủ yếu quan tâm đến việc triển khai logic cho 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();
    }
  }
}

Việc nhập SimpleChangeskhông cần thiết nếu không thay đổi thuộc tính đầu vào nào hoặc nếu bạn chỉ có một thuộc tính đầu vào.

Angular Doc: OnChanges

nếu không thì:

private _allowDay: boolean;

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

Chỉ tò mò, có lợi ích gì khi sử dụng ngOnChanges so với việc không sử dụng thuộc tính set nếu bạn chỉ quan tâm đến logic setter?
Mese

4
Không có sự khác biệt trong việc "sử dụng ngOnChanges so với không sử dụng tập hợp" ...;) Đùa sang một bên: Một lợi ích là, nếu thành phần của bạn có nhiều @Inputthuộc tính và bạn muốn gọi một thói quen khi bất kỳ trong số chúng đã thay đổi. Vì vậy, ít mã cần thiết.
Martin Schneider

Up, đã có một lỗi đánh máy hehe. Nhưng ok, nghĩ rằng nó có thể có liên quan nhiều hơn. Cảm ơn câu trả lời tho :)
Mese

1
@ MA-Maddin Tôi cho rằng bạn cũng có thể thiết lập một bản ghi có thể quan sát được nếu bạn đang mong đợi nhiều thay đổi cùng một lúc mà mỗi kết quả trong một thói quen cần phải được chạy.
Simon_Weaver

Cách tiếp cận ngOnChanges là tuyệt vời !! Câu trả lời tốt. Nếu giá trị được đặt không thể là riêng tư, ví dụ: nó được sử dụng làm ràng buộc trong mẫu, quy ước đặt tên / đặt tên riêng tư _propertyName trở nên không nhất quán. ngOnChanges có được điều này một cách hoàn hảo
Drenai

8

@Paul Cavacas, tôi đã có một vấn đề tương tự và tôi đã giải quyết bằng cách đặt trình Input()trang trí lên trên getter.

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

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

Xem trình tải này: https://plnkr.co/edit/6miSutgTe9sfEMCb8N4p?p=preview


6
Lỗi này khiến tôi phát điên, cuối cùng tôi thấy rằng bạn nên xác định Input () trước (getter hoặc setter nhưng trình trang trí đầu vào phải đi trước)
mã maxi

1
Đây là tài liệu tham khảo khác có thể giúp https://github.com/angular/angular/issues/5477
mã maxi

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.