Angular2 @Input กับคุณสมบัติที่มี get / set


178

ฉันมีองค์ประกอบ Angular2 ในองค์ประกอบนั้นในปัจจุบันมีเขตข้อมูลพวงที่มี @Input () นำไปใช้ก่อนหน้าพวกเขาเพื่ออนุญาตให้เชื่อมโยงกับคุณสมบัตินั้นเช่น

@Input() allowDay: boolean;

สิ่งที่ฉันต้องการจะทำคือผูกกับอสังหาริมทรัพย์ด้วยการรับ / การตั้งค่าเพื่อที่ฉันจะสามารถทำตรรกะอื่น ๆ บางอย่างในสุนัขที่ตั้งค่าดังต่อไปนี้

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

ฉันจะทำสิ่งนี้ใน Angular2 ได้อย่างไร

จากการแนะนำของ Thierry Templier ฉันเปลี่ยนเป็น แต่นั่นทำให้เกิดข้อผิดพลาดที่ไม่สามารถผูกกับ 'allowDay' ได้เนื่องจากไม่ใช่คุณสมบัติดั้งเดิมที่รู้จัก:

//@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ünterZöchbauer

ฉันอยากรู้ว่าคุณตั้งค่าการทดสอบหน่วยของคุณอย่างไรหากคุณไปตามเส้นทางของการใช้ set set ดังที่แสดงในคำตอบที่ยอมรับ
Winnemucca

1
ไม่ว่าคุณจะทำอะไรให้แน่ใจว่าใส่เบรกพอยต์หรือดีบั๊กหรือโต้กลับเข้าไปในหมาเซ็ทของคุณเพื่อให้แน่ใจว่ามันจะยิงได้แค่ครั้งเดียวตามที่คาดไว้ ฉันเพิ่งพบว่ามีการอัปเดตของฉันสำหรับการตรวจจับการเปลี่ยนแปลงทุกครั้งทำให้เกิดประสิทธิภาพที่น่ากลัวและพฤติกรรมที่แปลกประหลาด
Simon_Weaver

คำตอบ:


271

คุณสามารถตั้งค่า @Input บน setter โดยตรงดังที่อธิบายไว้ด้านล่าง:

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

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

ดู plunkr นี้: https://plnkr.co/edit/6miSutgTe9sfEMCb8N4p?p=preview


1
ฉันได้รับข้อผิดพลาดต่อไปนี้ไม่สามารถผูกกับ 'allowDay' ได้เนื่องจากไม่ใช่คุณสมบัติดั้งเดิมที่รู้จัก ดูคำถามที่อัปเดตเกี่ยวกับสิ่งที่ฉันเปลี่ยนรหัสไปเป็น
Paul Cavacas

คุณแน่ใจไหม? มันใช้งานได้สำหรับฉัน ฉันเพิ่มเสียงดังปัง บางทีคุณลืมที่จะเพิ่มคำสั่งลงในdirectivesแอตทริบิวต์ขององค์ประกอบที่คุณต้องการใช้มัน ... ฉันอัปเดตคำตอบของฉัน
Thierry Templier

2
นี่เป็นความคิดที่ไม่ดีเพราะถ้าคุณใช้ setter, ngOnChanges จะไม่ยิง
2867288


11
คำเตือน : สิ่งเหล่าsetterนี้จะไม่ถูกกระตุ้นโดยการกลายพันธุ์ไปยังค่าที่ถูกส่งผ่านโดยการอ้างอิง (เช่นการผลักไปยังอาร์เรย์การกลายพันธุ์วัตถุ ฯลฯ ) คุณจะต้องแทนที่ค่าทั้งหมดที่ถูกส่งผ่านInputเพื่อsetterให้การเรียกอีกครั้ง
Nickofthyme

61

หากคุณสนใจที่จะใช้ตรรกะเป็นหลักใน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();
    }
  }
}

การนำเข้าของSimpleChangesไม่จำเป็นถ้ามันไม่สำคัญว่าคุณสมบัติการป้อนข้อมูลที่มีการเปลี่ยนแปลงหรือถ้าคุณมีเพียงหนึ่งคุณสมบัติการป้อนข้อมูล

Doc Angular: OnChanges

มิฉะนั้น:

private _allowDay: boolean;

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

อยากรู้อยากเห็นมีประโยชน์สำหรับการใช้ ngOnChanges กับการไม่ใช้คุณสมบัติ set หรือไม่หากคุณสนใจเพียง setter logic?
Mese

4
ไม่มีความแตกต่างใน "การใช้ ngOnChanges กับการไม่ใช้ชุด" ... ;) การล้อเล่น: ข้อดีอย่างหนึ่งคือถ้าองค์ประกอบของคุณมี@Inputคุณสมบัติหลายอย่างและคุณต้องการเรียกรูทีนเมื่อมีการเปลี่ยนแปลงใด ๆ รหัสน้อยจึงจำเป็น
Martin Schneider

อัพมีพิมพ์ผิดฮิฮิ แต่ตกลงคิดว่าอาจมีความเกี่ยวข้องมากกว่า ขอบคุณสำหรับคำตอบสรรพสินค้าใหญ่ :)
Mese

1
@ MA-Maddin ฉันคิดว่าคุณสามารถตั้งค่า debounce ที่สังเกตได้ถ้าคุณคาดหวังว่าจะมีการเปลี่ยนแปลงหลายอย่างในเวลาเดียวกันซึ่งแต่ละผลลัพธ์จะส่งผลให้รูทีนจำเป็นต้องถูกเรียกใช้
Simon_Weaver

วิธีการ ngOnChanges ดีมาก !! คำตอบที่ดี. หากค่าที่ตั้งไว้ไม่สามารถเป็นส่วนตัวได้เช่นมันถูกใช้เป็นการเชื่อมโยงในเทมเพลตแผนการตั้งชื่อ _propertyName setter / private จะไม่สอดคล้องกัน ngOnChanges ได้รับสิ่งนี้อย่างสมบูรณ์แบบ
Drenai

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
ข้อผิดพลาดนี้ทำให้ฉันเป็นบ้าในที่สุดฉันก็พบว่าคุณควรกำหนดอินพุต () ก่อน (ทะเยอทะยานหรือ setter แต่มัณฑนากรป้อนข้อมูลจะต้องไปก่อน)
maxi-code

1
นี่คือข้อมูลอ้างอิงอื่น ๆ ที่อาจช่วยhttps://github.com/angular/angular/angular/issues/5477
รหัส maxi

1

อัปเดตคำตอบที่ยอมรับสำหรับเชิงมุม 7.0.1 บน stackblitz ที่นี่: https://stackblitz.com/edit/angular-inputsetter?embed=1&file=src/app/app.component.ts

directivesไม่มีอยู่ในตัวเลือก Component decorator ดังนั้นฉันจึงได้ให้คำสั่งย่อยเพื่อโมดูลแอป

ขอบคุณ@ thierry-templier !

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.