ตั้งค่าด้วยตนเองสำหรับการควบคุม FormBuilder


176

นี่คือการขับรถฉันบ้าฉันอยู่ภายใต้ปืนและไม่สามารถที่จะใช้เวลาอีกทั้งวันนี้

ฉันกำลังพยายามตั้งค่าการควบคุม ('dept') ด้วยตนเองภายในองค์ประกอบและมันก็ใช้งานไม่ได้ - แม้กระทั่งค่าบันทึกใหม่เพื่อคอนโซลอย่างถูกต้อง

นี่คืออินสแตนซ์ของ FormBuilder:

initForm() {
  this.form = this.fb.group({
    'name': ['', Validators.required],
    'dept': ['', Validators.required],
    'description': ['', Validators.required],
  });
}

นี่คือตัวจัดการเหตุการณ์ที่ได้รับฝ่ายที่เลือก:

deptSelected(selected: { id: string; text: string }) {
  console.log(selected) // Shows proper selection!

  // This is how I am trying to set the value
  this.form.controls['dept'].value = selected.id;
}

ตอนนี้เมื่อมีการส่งแบบฟอร์มและฉันออกจากระบบthis.formฟิลด์ยังว่างเปล่า! ฉันเห็นการใช้ ppl อื่น ๆupdateValue()แต่นี่เป็น beta.1 และฉันไม่เห็นว่าเป็นวิธีที่ถูกต้องในการเรียกใช้ตัวควบคุม

ฉันได้ลองโทรแล้วupdateValueAndValidity()โดยไม่ประสบความสำเร็จด้วย :(

ฉันจะใช้ngControl="dept"กับองค์ประกอบของฟอร์มเช่นฉันทำกับส่วนที่เหลือของฟอร์ม แต่เป็นคำสั่ง / ส่วนประกอบที่กำหนดเอง

<ng-select
  [data]="dept"
  [multiple]="false"
  [items]="depts"
  (selected)="deptSelected($event)" <!-- This is how the value gets to me -->
  [placeholder]="'No Dept Selected'"></ng-select>

ฉันพบสถานการณ์ที่คล้ายกันสถานการณ์คือค่าที่ตั้งไว้ใน http.get-subscriber และโหลดค่าฟอร์ม แต่การตั้งค่าบรรทัดการเรียกใช้งานก่อนการสมัครจริงจะดำเนินการในภายหลังแบบอะซิงโครนัส ดังนั้นการตั้งค่าในการสมัครสมาชิกให้แน่ใจว่ามันตั้งค่า my2cents!
HydTechie

คำตอบ:


326

อัปเดต: 19/03/2017

this.form.controls['dept'].setValue(selected.id);

อายุ:

ตอนนี้เราถูกบังคับให้ทำแบบตัวละคร:

(<Control>this.form.controls['dept']).updateValue(selected.id)

ไม่หรูหรามากฉันเห็นด้วย หวังว่าจะได้รับการปรับปรุงในรุ่นอนาคต


6
มันใช้งานได้ดีขอบคุณ ยังต้องล้างการตรวจสอบ: (<Control>this.form.controls['dept']).setErrors(null)
ผู้ชายที่เรียกว่า Haney

17
หรือยังthis.form.get('dept').setValue(selected.id):)
พัฒนา

6
เพียงแค่ทราบ คุณยังสามารถเข้าถึงคุณสมบัติโดยตรงโดยไม่มีตัวทำดัชนี this.form.controls.dept.setValue(selected.id);
James Poulose

แต่สิ่งนี้จะไม่ทำการตรวจสอบความถูกต้องของข้อมูลใหม่ !! จะทริกเกอร์การตรวจจับการเปลี่ยนแปลงด้วยตนเองหลังจากอัพเดตได้อย่างไร?
ksh

1
มันเป็นปี 2019 สำหรับฉันงานนี้:this.form.controls['dept'].setValue(selected.id);
John Lopez

98

ใน Angular 2 Final (RC5 +) มี API ใหม่สำหรับการปรับปรุงค่าแบบฟอร์ม patchValue()วิธี API สนับสนุนการปรับปรุงรูปแบบบางส่วนที่เราจะต้องระบุบางส่วนของเขตข้อมูล:

this.form.patchValue({id: selected.id})

นอกจากนี้ยังมีsetValue()วิธี API ที่ต้องการวัตถุที่มีเขตข้อมูลแบบฟอร์มทั้งหมด หากไม่มีฟิลด์เราจะได้รับข้อผิดพลาด


7
เพียงเพื่อเพิ่มที่ ณ ขณะนี้updateValue(จากคำตอบที่ยอมรับโดย Filoche) จะถูกคัดค้านในความโปรดปรานของsetValue
superjos

2
นี่คือคำขอดึงอย่างเป็นทางการบน Github และเหตุผลในการเลิกupdateValue()และแนะนำและpatchValue setValue
TheBrockEllis

แต่สิ่งนี้จะไม่ทำการตรวจสอบความถูกต้องของข้อมูลใหม่ !! วิธีการทริกเกอร์การตรวจจับการเปลี่ยนแปลงด้วยตนเองหลังจากอัปเดต
ksh

16

Aangular 2 final มี API ที่อัปเดตแล้ว พวกเขาได้เพิ่มวิธีการมากมายสำหรับสิ่งนี้

หากต้องการอัปเดตการควบคุมฟอร์มจากคอนโทรลเลอร์ให้ทำดังนี้

this.form.controls['dept'].setValue(selected.id);

this.form.controls['dept'].patchValue(selected.id);

ไม่จำเป็นต้องรีเซ็ตข้อผิดพลาด

อ้างอิง

https://angular.io/docs/ts/latest/api/forms/index/FormControl-class.html

https://toddmotto.com/angular-2-form-controls-patch-value-set-value


ความแตกต่างระหว่างสอง - setValue()เมื่อเรียกใช้บนformGroup/formBuilderมันต้องมีค่าทั้งหมดภายใต้แบบฟอร์มที่จะตั้งค่า patchValue()เมื่อเรียกใช้บนเดียวกันสามารถใช้เพื่ออัพเดตค่าเฉพาะ
Vibhor Dube

11

คุณสามารถใช้วิธีการต่อไปนี้เพื่อปรับปรุงค่าของตัวควบคุมฟอร์มที่มีปฏิกิริยา วิธีการต่อไปนี้จะเหมาะกับความต้องการของคุณ

วิธีการใช้ setValue ()

this.form.get("dept").setValue(selected.id);
this.form.controls["dept"].setValue(selected.id);

วิธีการใช้ patchValue ()

this.form.get("dept").patchValue(selected.id);
this.form.controls['dept'].patchValue(selected.id);
this.form.patchValue({"dept": selected.id});

วิธีสุดท้ายจะวนลูปตัวควบคุมทั้งหมดในแบบฟอร์มอย่างละเอียดดังนั้นจึงไม่ต้องการเมื่ออัปเดตตัวควบคุมเดียว

คุณสามารถใช้วิธีการใดก็ได้ภายในตัวจัดการเหตุการณ์

deptSelected(selected: { id: string; text: string }) {
     // any of the above method can be added here
}

คุณสามารถอัปเดตตัวควบคุมหลายตัวในกลุ่มฟอร์มได้หากต้องการโดยใช้

this.form.patchValue({"dept": selected.id, "description":"description value"});

9

คุณสามารถลองสิ่งนี้:

deptSelected(selected: { id: string; text: string }) {
  console.log(selected) // Shows proper selection!

  // This is how I am trying to set the value
  this.form.controls['dept'].updateValue(selected.id);
}

สำหรับรายละเอียดเพิ่มเติมคุณสามารถดู JS Doc ที่เกี่ยวข้องเกี่ยวกับพารามิเตอร์ตัวที่สองของupdateValueวิธีการ: https://github.com/angular/angular/angular/blob/master/modules/angular2/src/common/forms/model TS


ขอบคุณสำหรับคำตอบของคุณ - อย่างไรก็ตาม updateValue ดูเหมือนจะเป็นวิธีที่ไม่ถูกต้องใน angular2 beta.1 - คุณใช้เวอร์ชันนั้นในเวอร์ชันใดอยู่
Matthew Brown

1
typescript error TS2339: Property 'updateValue' does not exist on type 'AbstractControl'ให้ข้อผิดพลาดต่อไปนี้: ControlGroupในองค์ประกอบที่แบบฟอร์มมีประเภทของ บางทีถ้าฉันสร้างพวกเขาทีละคนด้วยnew Control()สิ่งนี้จะใช้ได้
Matthew Brown

5

สิ่งเหล่านี้ไม่ได้ผลสำหรับฉัน ฉันต้องทำ:

  this.myForm.get('myVal').setValue(val);

เกิดขึ้นกับฉันเหมือนกัน ทำไมเป็นกรณีนี้
Rehmanali Momin

3
  let cloneObj = Object.assign({}, this.form.getRawValue(), someClass);
  this.form.complexForm.patchValue(cloneObj);

หากคุณไม่ต้องการตั้งค่าแต่ละฟิลด์ด้วยตนเอง


2

โซลูชันที่อัปเดต Angular 2 ของ @ Filoche การใช้FormControl

(<Control>this.form.controls['dept']).updateValue(selected.id)

import { FormControl } from '@angular/forms';

(<FormControl>this.form.controls['dept']).setValue(selected.id));

หรือคุณสามารถใช้โซลูชันของ @ AngularUniversity ที่ใช้patchValue


1

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

โครงสร้างแบบฟอร์มของคุณสมบูรณ์แบบมากที่จะใช้เป็นตัวอย่าง ดังนั้นตลอดคำตอบของฉันฉันจะแสดงว่าเป็นแบบฟอร์ม

this.form = this.fb.group({
    'name': ['', Validators.required],
    'dept': ['', Validators.required],
    'description': ['', Validators.required]
  });

ดังนั้นรูปแบบของเราเป็นFormGroupชนิดของวัตถุที่มีสามFormControl

มีสองวิธีในการอัพเดตค่ารุ่น:

  • ใช้เมธอด setValue () เพื่อตั้งค่าใหม่สำหรับการควบคุมส่วนบุคคล เมธอด setValue () ปฏิบัติตามโครงสร้างของกลุ่มฟอร์มอย่างเคร่งครัดและแทนที่ค่าทั้งหมดสำหรับการควบคุม

  • ใช้เมธอด patchValue () เพื่อแทนที่คุณสมบัติใด ๆ ที่กำหนดไว้ในวัตถุที่เปลี่ยนแปลงในรูปแบบของแบบฟอร์ม

การตรวจสอบอย่างเข้มงวดของเมธอด setValue () จะช่วยตรวจจับข้อผิดพลาดในการซ้อนในรูปแบบที่ซับซ้อนขณะที่ patchValue () ล้มเหลวอย่างเงียบ ๆ ในข้อผิดพลาดเหล่านั้น

จากเอกสารอย่างเป็นทางการของ Angular ที่นี่

ดังนั้นเมื่ออัปเดตค่าสำหรับอินสแตนซ์กลุ่มฟอร์มที่มีการควบคุมหลายอย่าง แต่คุณอาจต้องการอัปเดตบางส่วนของโมเดล patchValue () เป็นสิ่งที่คุณกำลังมองหา

ลองดูตัวอย่าง เมื่อคุณใช้patchValue ()

this.form.patchValue({
    dept: 1 
});
//here we are just updating only dept field and it will work.

แต่เมื่อคุณใช้setValue ()คุณจะต้องอัปเดตโมเดลเต็มเนื่องจากจะยึดตามโครงสร้างของกลุ่มฟอร์มอย่างเคร่งครัด ดังนั้นถ้าเราเขียน

this.form.setValue({
    dept: 1 
});
// it will throw error.

เราจะต้องผ่านคุณสมบัติทั้งหมดของรูปแบบกลุ่มแบบฟอร์ม แบบนี้

this.form.setValue({
      name: 'Mr. Bean'
      dept: 1,
      description: 'spome description'
  });

แต่ฉันไม่ได้ใช้สไตล์นี้บ่อยๆ ฉันชอบใช้วิธีการต่อไปนี้ซึ่งช่วยให้โค้ดของฉันสะอาดขึ้นและสามารถเข้าใจได้ง่ายขึ้น

สิ่งที่ฉันทำคือฉันประกาศการควบคุมทั้งหมดเป็นตัวแปรแยกและใช้ setValue () เพื่ออัปเดตการควบคุมเฉพาะนั้น

สำหรับแบบฟอร์มด้านบนฉันจะทำอะไรแบบนี้

get companyIdentifier(): FormControl {
    return this.form.get('name') as FormControl;
}

get dept(): FormControl {
    return this.form.get('dept') as FormControl;
}

get description(): FormControl {
    return this.form.get('description') as FormControl;
}

เมื่อคุณต้องการอัปเดตตัวควบคุมฟอร์มให้ใช้คุณสมบัตินั้นเพื่ออัปเดต ในตัวอย่างผู้ถามพยายามอัปเดตการควบคุมฟอร์มฝ่ายเมื่อผู้ใช้เลือกรายการจากรายการแบบหล่นลง

deptSelected(selected: { id: string; text: string }) {
  console.log(selected) // Shows proper selection!

  // instead of using this.form.controls['dept'].setValue(selected.id), I prefer the following.

  this.dept.setValue(selected.id); // this.dept is the property that returns the 'dept' FormControl of the form.
}

ฉันขอแนะนำให้ดูAPI ของ FormGroupเพื่อรับทราบคุณสมบัติและวิธีการทั้งหมดของ FormGroup

เพิ่มเติม : รู้เกี่ยวกับทะเยอทะยานดูที่นี่


1

หากคุณใช้การควบคุมแบบฟอร์มวิธีที่ง่ายที่สุดในการทำเช่นนี้:

this.FormName.get('ControlName').setValue(value);

-1

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

Must supply a value for form control with name: 'stateOrProvince'.

ดังนั้นคุณอาจถูกล่อลวงให้ใช้patchValueแต่สิ่งนี้อาจเป็นอันตรายได้หากคุณพยายามอัปเดตทั้งฟอร์ม ฉันมีสิ่งaddressที่อาจไม่มีstateOrProvinceหรือstateCdขึ้นอยู่กับว่าเป็นสหรัฐอเมริกาหรือทั่วโลก

แต่คุณสามารถอัปเดตดังนี้ - ซึ่งจะใช้ค่า null เป็นค่าเริ่มต้น:

this.form.setValue( { stateOrProvince: null, stateCd: null, ...address } );
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.