【问题标题】:Remove all items from a FormArray in Angular从 Angular 中的 FormArray 中删除所有项目
【发布时间】:2017-06-10 16:02:21
【问题描述】:

我在 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

【问题讨论】:

标签: angular angular2-forms


【解决方案1】:

我有同样的问题。有两种方法可以解决这个问题。

保留订阅

您可以通过在循环中调用removeAt(i) 函数来手动清除每个FormArray 元素。

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

这种方法的优点是您的formArray 上的任何订阅(例如在formArray.valueChanges 注册的订阅)都不会丢失。

请参阅FormArray documentation 了解更多信息。


更清洁的方法(但会破坏订阅引用)

您可以将整个 FormArray 替换为新的。

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

如果您订阅了 formArray.valueChanges observable,这种方法会导致问题!如果您将 FromArray 替换为新数组,您将丢失对您订阅的 observable 的引用。

【讨论】:

  • 从 Angular 8+ 开始,从 FormArray 中删除所有组件的首选方法是使用 formArray.clear();
  • 另外,yourFormArray.setValue([]));和 yourFormGroup.setControl('yourFormArray', []);
  • 再见验证这种方法
  • @Renan 我正在使用 formControl
【解决方案2】:

或者您可以简单地清除控件

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

【讨论】:

  • “arr.controls = [];”提及真的很棒!
  • @Pian, 只有 const arr = this.myForm.controls.arr; arr.controls = [];正在努力清除表单数组。 TQ
  • inFormArray.at(1).remove(); 给了我一个[ts] Property 'remove' does not exist on type 'AbstractControl'. 编译器错误。
  • @Pian0_M4n 在你的模板中,let c of inFormArray 应该是let c of inFormArray.controls ?
【解决方案3】:

从 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

【讨论】:

  • 这在 Angular 13 中仍然有效
【解决方案4】:

Angular 8

只需在 formArrays 上使用 clear() 方法:

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

【讨论】:

    【解决方案5】:

    警告!

    Angular v6.1.7 FormArray documentation 说:

    要更改数组中的控件,请使用 push、insert 或 removeAt FormArray 本身的方法。这些方法可确保控制 在表单的层次结构中正确跟踪。不要修改数组 AbstractControls 用于直接实例化 FormArray,因为 导致奇怪和意外的行为,例如损坏的变化 检测。

    如果您直接在 controls 数组上使用 splice 函数作为建议的答案之一,请记住这一点。

    使用removeAt 函数。

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

    【讨论】:

      【解决方案6】:

      Angular v4.4 如果您需要保存对 FormArray 实例的相同引用,请尝试以下操作:

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

      【讨论】:

      • 在从数组中弹出元素的同时保留订阅的好方法。
      • @mtpultz 请注意已接受答案的更改日志 (stackoverflow.com/posts/41856927/revisions)。当我离开这个答案时,接受的答案与当前不同。
      【解决方案7】:

      您可以轻松地为您的数组定义一个 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()
        }
      

      【讨论】:

        【解决方案8】:

        更新:Angular 8 终于有了清除数组的方法 FormArray.clear()

        【讨论】:

          【解决方案9】:

          使用 FormArray.clear() 删除 FormArray 中数组的所有元素

          【讨论】:

            【解决方案10】:

            简单

            formArray.clear()
            

            足够了

            【讨论】:

            • 这应该是现在公认的答案。
            【解决方案11】:

            从 Angular 8 开始,您可以使用 this.formArray.clear() 清除表单数组中的所有值。 这是一种更简单、更有效的替代方法,可以逐个删除所有元素

            【讨论】:

              【解决方案12】:

              提供了数据结构,用于将数组中的信息替换为匹配的内容,您可以使用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

              reset(value?: any, {onlySelf, emitEvent}?: {onlySelf?: boolean, emitEvent?: boolean}) : void 重置 FormArray。这意味着通过 默认:

              数组和所有后代都被标记为原始数组和所有 后代被标记为未触及所有后代的值将是 null 或 null 映射您还可以通过以下方式重置为特定的表单状态 传入与结构相匹配的状态数组 控制。状态可以是独立值或表单状态对象 同时具有值​​和禁用状态。

              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'
              

              【讨论】:

              • 这肯定意味着数组中的项目数必须完全相同?
              【解决方案13】:

              我从未尝试过使用 formArray,我一直使用 FormGroup,您可以使用以下方法删除所有控件:

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

              作为 formGroup 的一个实例。

              【讨论】:

                【解决方案14】:

                为了保持代码简洁,我为使用 Angular 7 及以下版本的任何人创建了以下扩展方法。这也可以用于扩展响应式表单的任何其他功能。

                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;
                }
                
                

                【讨论】:

                  【解决方案15】:

                  我很晚了,但我找到了其他不需要循环的方法。您可以通过将数组控件设置为空来重置数组。

                  以下代码将重置您的数组。

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

                  【讨论】:

                    【解决方案16】:

                    如果数组有 100 个项目,则循环将需要很长时间才能删除所有项目。您可以清空 FormArray 的控件和值属性,如下所示。

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

                    【讨论】:

                      【解决方案17】:

                      如果您使用的是 Angular 7 或以前的版本,并且您无权访问 clear() 方法,则有一种方法可以在不执行任何循环的情况下实现:

                      yourFormGroup.controls.youFormArrayName = new FormArray([]);
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2021-09-02
                        • 2020-02-11
                        • 2012-03-11
                        • 1970-01-01
                        • 2020-05-29
                        相关资源
                        最近更新 更多