ลบรายการทั้งหมดออกจาก FormArray ใน Angular


87

ฉันมีอาร์เรย์แบบฟอร์มภายใน FormBuilder และฉันกำลังเปลี่ยนฟอร์มแบบไดนามิกเช่นเมื่อคลิกโหลดข้อมูลจากแอปพลิเคชัน 1 เป็นต้น

ปัญหาที่ฉันพบคือข้อมูลทั้งหมดโหลด แต่ข้อมูลใน FormArray ยังคงอยู่และเพียงแค่เชื่อมรายการเก่ากับใหม่

ฉันจะล้าง FormArray ให้มีเฉพาะรายการใหม่ได้อย่างไร

ฉันได้ลองสิ่งนี้แล้ว

const control2 = <FormArray>this.registerForm.controls['other_Partners'];
control2.setValue([]);

แต่มันไม่ได้ผล

ความคิดใด ๆ ?

ngOnInit(): void {
  this.route.params.subscribe(params => {
    if (params['id']) {
      this.id = Number.parseInt(params['id']);
    } else { this.id = null;}
  });
  if (this.id != null && this.id != NaN) {
    alert(this.id);
    this.editApplication();
    this.getApplication(this.id);
  } else {
    this.newApplication();
  }
}

onSelect(Editedapplication: Application) {
  this.router.navigate(['/apply', Editedapplication.id]);
}

editApplication() {
  this.registerForm = this.formBuilder.group({
    id: null,
    type_of_proposal: ['', Validators.required],
    title: ['', [Validators.required, Validators.minLength(5)]],
    lead_teaching_fellow: ['', [Validators.required, Validators.minLength(5)]],
    description: ['', [Validators.required, Validators.minLength(5)]],
    status: '',
    userID: JSON.parse(localStorage.getItem('currentUser')).username,
    contactEmail: JSON.parse(localStorage.getItem('currentUser')).email,
    forename: JSON.parse(localStorage.getItem('currentUser')).firstname,
    surname: JSON.parse(localStorage.getItem('currentUser')).surname,
    line_manager_discussion: true,
    document_url: '',
    keywords: ['', [Validators.required, Validators.minLength(5)]],
    financial_Details: this.formBuilder.group({
      id: null,
      buying_expertise_description: ['', [Validators.required, Validators.minLength(2)]],
      buying_expertise_cost: ['', [Validators.required]],
      buying_out_teaching_fellow_cost: ['', [Validators.required]],
      buying_out_teaching_fellow_desc: ['', [Validators.required, Validators.minLength(2)]],
      travel_desc: ['', [Validators.required, Validators.minLength(2)]],
      travel_cost: ['', [Validators.required]],
      conference_details_desc: ['', [Validators.required, Validators.minLength(2)]],
      conference_details_cost: ['', [Validators.required]],
    }),

    partners: this.formBuilder.array([
        //this.initEditPartner(),
        //this.initEditPartner()
        // this.initMultiplePartners(1)
      ]
    ),
    other_Partners: this.formBuilder.array([
      //this.initEditOther_Partners(),
    ])
  });
}

getApplication(id) {
  this.applicationService.getAppById(id, JSON.parse(localStorage.getItem('currentUser')).username)
    .subscribe(Response => {
      if (Response.json() == false) {
        this.router.navigateByUrl('/');
      } else {
        this.application = Response.json();
        for (var i = 0; i < this.application.partners.length;i++) {
          this.addPartner();
        }
        for (var i = 0; i < this.application.other_Partners.length; i++) {
          this.addOther_Partner();
        }

        this.getDisabledStatus(Response.json().status);
        (<FormGroup>this.registerForm) .setValue(Response.json(), { onlySelf: true });
      }
    });
}

ngOnInit ไม่ถูกเรียกเมื่อคลิก


คำตอบ:


148

ฉันมีปัญหาเดียวกัน มีสองวิธีในการแก้ปัญหานี้

รักษาการสมัครสมาชิก

คุณสามารถล้างองค์ประกอบ FormArray แต่ละรายการด้วยตนเองได้โดยเรียกใช้removeAt(i)ฟังก์ชันแบบวนซ้ำ

clearFormArray = (formArray: FormArray) => {
  while (formArray.length !== 0) {
    formArray.removeAt(0)
  }
}

ข้อดีของแนวทางนี้คือการสมัครสมาชิกใด ๆ บนของคุณformArrayเช่นที่ลงทะเบียนไว้formArray.valueChangesจะไม่สูญหายไป

ดูเอกสาร FormArrayสำหรับข้อมูลเพิ่มเติม


วิธีการทำความสะอาด (แต่ทำลายการอ้างอิงการสมัครสมาชิก)

คุณสามารถแทนที่ FormArray ทั้งหมดด้วยอันใหม่ได้

clearFormArray = (formArray: FormArray) => {
  formArray = this.formBuilder.array([]);
}

วิธีนี้ทำให้เกิดปัญหาหากคุณสมัครรับข้อมูลที่formArray.valueChangesสังเกตได้! หากคุณแทนที่ FromArray ด้วยอาร์เรย์ใหม่คุณจะสูญเสียการอ้างอิงไปยังสิ่งที่สังเกตได้ที่คุณสมัครใช้งาน


73
สำหรับ Angular 8+ วิธีที่ต้องการในการลบส่วนประกอบทั้งหมดจาก FormArray ใช้formArray.clear();
Renan

2
นอกจากนี้ yourFormArray.setValue ([])); และ yourFormGroup.setControl ('yourFormArray', []);
ออสการ์

1
ลาก่อนการตรวจสอบด้วยวิธีนี้
Andre Elrico

@Renan ฉันใช้ formControl
Emir Herrera

31

หรือคุณสามารถล้างการควบคุม

this.myForm= {
     name: new FormControl(""),
     desc: new FormControl(""),
     arr: new FormArray([])
}

เพิ่มบางอย่าง array

const arr = <FormArray>this.myForm.controls.arr;
arr.push(new FormControl("X"));

ล้างอาร์เรย์

const arr = <FormArray>this.myForm.controls.arr;
arr.controls = [];

เมื่อคุณเลือกหลายทางเลือกและชัดเจนบางครั้งก็ไม่อัปเดตมุมมอง วิธีแก้ปัญหาคือการเพิ่ม

arr.removeAt(0)

อัปเดต

โซลูชันที่สวยงามกว่าในการใช้อาร์เรย์แบบฟอร์มคือการใช้ getter ที่ด้านบนสุดของชั้นเรียนจากนั้นคุณจะสามารถเข้าถึงได้

get inFormArray(): FormArray {
    this.myForm.get('inFormArray') as FormArray;
}

และเพื่อใช้ในเทมเพลต

<div *ngFor="let c of inFormArray; let i = index;" [formGroup]="i">
other tags...
</div>

รีเซ็ต:

inFormArray.reset();

กด:

inFormArray.push(new FormGroup({}));

ลบค่าที่ดัชนี: 1

inFormArray.removeAt(1);

อัปเดต 2:

รับวัตถุบางส่วนรับข้อผิดพลาดทั้งหมดเป็น JSON และคุณสมบัติอื่น ๆ อีกมากมายใช้NaoFormsModule


6
"arr.controls = [];" พูดถึงเยี่ยมจริงๆ!
dotNetkow

@ เพียรเฉพาะ const arr = <FormArray> this.myForm.controls.arr; arr.controls = []; กำลังดำเนินการล้างฟอร์มอาร์เรย์ TQ
chandoo

inFormArray.at(1).remove(); ทำให้ฉันมี[ts] Property 'remove' does not exist on type 'AbstractControl'.ข้อผิดพลาดในการขนส่ง
zgue

@ Pian0_M4n ในเทมเพลตของคุณlet c of inFormArrayควรเป็นlet c of inFormArray.controlsอย่างไร
วอล

23

ตั้งแต่ Angular 8+ คุณสามารถใช้clear()เพื่อลบการควบคุมทั้งหมดใน FormArray:

const arr = new FormArray([
   new FormControl(),
   new FormControl()
]);
console.log(arr.length);  // 2

arr.clear();
console.log(arr.length);  // 0

สำหรับเวอร์ชันก่อนหน้าวิธีที่แนะนำคือ:

while (arr.length) {
   arr.removeAt(0);
}

https://angular.io/api/forms/FormArray#clear


1
ขอขอบคุณที่กล่าวถึง Angular 8+ ที่นี่
Patrick Hillert

11

เชิงมุม 8

เพียงใช้clear()วิธีการใน formArrays:

(this.invoiceForm.controls['other_Partners'] as FormArray).clear();

8

Angular v4.4 หากคุณต้องการบันทึกการอ้างอิงเดียวกันกับอินสแตนซ์ของ FormArray ให้ลองทำดังนี้:

purgeForm(form: FormArray) {
  while (0 !== form.length) {
    form.removeAt(0);
  }
}

วิธีที่ดีในการรักษาการสมัครสมาชิกในขณะที่ดึงองค์ประกอบออกจากอาร์เรย์
red_dorian

@mtpultz โปรดสังเกตการเปลี่ยนแปลง ( stackoverflow.com/posts/41856927/revisions ) ของคำตอบที่ยอมรับ ในช่วงเวลาที่ฉันออกจากคำตอบนี้ยอมรับว่าคำตอบนั้นแตกต่างจากปัจจุบัน
Alex Dzeiko

8

คำเตือน!

เอกสาร FormArrayเชิงมุมv6.1.7 ระบุว่า:

ในการเปลี่ยนคอนโทรลในอาร์เรย์ให้ใช้เมธอด push, insert หรือ removeAt ใน FormArray เอง วิธีการเหล่านี้ช่วยให้มั่นใจได้ว่าการควบคุมได้รับการติดตามอย่างถูกต้องในลำดับชั้นของฟอร์ม อย่าแก้ไขอาร์เรย์ของ AbstractControls ที่ใช้ในการสร้างอินสแตนซ์ FormArray โดยตรงเนื่องจากจะทำให้เกิดพฤติกรรมแปลก ๆ และไม่คาดคิดเช่นการตรวจจับการเปลี่ยนแปลงที่เสียไป

โปรดจำไว้ว่าหากคุณใช้spliceฟังก์ชันนี้โดยตรงกับcontrolsอาร์เรย์ตามคำตอบที่แนะนำ

ใช้removeAtฟังก์ชัน

  while (formArray.length !== 0) {
    formArray.removeAt(0)
  }

6

คุณสามารถกำหนด getter สำหรับอาร์เรย์ของคุณได้อย่างง่ายดายและล้างมันดังนี้:

  formGroup: FormGroup    
  constructor(private fb: FormBuilder) { }

  ngOnInit() {
    this.formGroup = this.fb.group({
      sliders: this.fb.array([])
    })
  }
  get sliderForms() {
    return this.formGroup.get('sliders') as FormArray
  }

  clearAll() {
    this.formGroup.reset()
    this.sliderForms.clear()
  }



4

เนื่องจาก Angular 8 คุณสามารถใช้this.formArray.clear()เพื่อล้างค่าทั้งหมดในอาร์เรย์ฟอร์ม เป็นทางเลือกที่ง่ายและมีประสิทธิภาพมากกว่าในการลบองค์ประกอบทั้งหมดทีละรายการ


3

จัดเตรียมโครงสร้างข้อมูลสำหรับสิ่งที่คุณจะแทนที่ข้อมูลในอาร์เรย์โดยตรงกับสิ่งที่มีอยู่แล้วที่คุณสามารถใช้ได้ patchValue

https://angular.io/docs/ts/latest/api/forms/index/FormArray-class.html#!#reset-anchor

patchValue (value: any [], {onlySelf, emitEvent}?: {onlySelf ?: boolean, emitEvent ?: boolean}): void แก้ไขค่าของ FormArray ยอมรับอาร์เรย์ที่ตรงกับโครงสร้างของตัวควบคุมและจะพยายามอย่างเต็มที่เพื่อจับคู่ค่ากับตัวควบคุมที่ถูกต้องในกลุ่ม

ยอมรับทั้งชุดซุปเปอร์และชุดย่อยของอาร์เรย์โดยไม่มีข้อผิดพลาด

const arr = new FormArray([
   new FormControl(),
   new FormControl()
]);
console.log(arr.value);   // [null, null]
arr.patchValue(['Nancy']);
console.log(arr.value);   // ['Nancy', null]

หรือคุณสามารถใช้ reset

รีเซ็ต (ค่า?: any, {onlySelf, emitEvent}?: {onlySelf ?: boolean, emitEvent ?: boolean}): เป็นโมฆะรีเซ็ต FormArray ซึ่งหมายความว่าโดยค่าเริ่มต้น:

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

this.arr.reset(['name', 'last name']);
console.log(this.arr.value);  // ['name', 'last name']

หรือ

this.arr.reset([   {value: 'name', disabled: true},   'last' ]);
console.log(this.arr.value);  // ['name', 'last name']
console.log(this.arr.get(0).status);  // 'DISABLED'

นี่คือการสาธิต Plunker ที่แยกออกจากงานก่อนหน้านี้ของฉันซึ่งสาธิตการใช้งานที่ง่ายมาก


นั่นหมายความว่าคุณต้องมีจำนวนรายการในอาร์เรย์เท่ากันหรือไม่?
Simon_Weaver

2

ฉันไม่เคยลองใช้ formArray ฉันทำงานกับ FormGroup มาตลอดและคุณสามารถลบการควบคุมทั้งหมดโดยใช้:

Object.keys(this.formGroup.controls).forEach(key => {
          this.formGroup.removeControl(key);
        });

เป็น formGroup อินสแตนซ์ของ FormGroup


1

เพื่อให้โค้ดสะอาดฉันได้สร้างวิธีการขยายต่อไปนี้สำหรับทุกคนที่ใช้ Angular 7 และต่ำกว่า นอกจากนี้ยังสามารถใช้เพื่อขยายฟังก์ชันการทำงานอื่น ๆ ของ Reactive Forms

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

declare module '@angular/forms/src/model' {
  interface FormArray {
    clearArray: () => FormArray;
  }
}

FormArray.prototype.clearArray = function () {
  const _self = this as FormArray;
  _self.controls = [];
  _self.setValue([]);
  _self.updateValueAndValidity();
  return _self;
}


1

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

ด้านล่างโค้ดจะรีเซ็ตอาร์เรย์ของคุณ

this.form.setControl('name', this.fb.array([]))


0

แม้ว่าการวนซ้ำจะใช้เวลานานในการลบรายการทั้งหมดหากอาร์เรย์มีรายการ 100 รายการ คุณสามารถว่างเปล่าทั้งตัวควบคุมและคุณสมบัติค่าของ FormArray ดังด้านล่าง

clearFormArray = (formArray: FormArray) => {formArray.controls = []; formArray.setValue ([]); }


0

หากคุณใช้ Angular 7 หรือเวอร์ชันก่อนหน้าและคุณไม่สามารถเข้าถึงเมธอด clear () ได้มีวิธีที่จะทำให้สำเร็จได้โดยไม่ต้องวนซ้ำ:

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