angular 2从formarray中删除所有项目


86

我在formbuilder中有一个表单数组,并且我正在动态更改表单,即在单击加载来自应用程序1等的数据时。

我遇到的问题是,所有数据都已加载,但formarray中的数据仍然保留,只是将旧项与新项合并。

我如何清除该formarray仅包含新项目。

我已经试过了

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

但这不起作用。

有任何想法吗?谢谢

在nginit中

ngOnInit(): void {
this.route.params.subscribe(params => { alert(params['id']);
            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 }); 
                      }

                }
         
        );

       
        
        

       
    }

点击时未调用ngonitit


一个相关的问题在这里跟踪的角度回购
E.桑丁

Answers:


145

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

保留订阅

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

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

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

有关更多信息,请参见FormArray文档


更干净的方法(但会破坏订阅引用)

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

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

如果您订阅了formArray.valueChanges可观察的方法,则此方法会导致问题!如果将FromArray替换为新数组,则将丢失对已订阅的可观察对象的引用。


67
从Angular 8开始,从FormArray删除所有组件的首选方法是使用formArray.clear();
Renan

2
另外,yourFormArray.setValue([])); 和yourFormGroup.setControl('yourFormArray',[]);
奥斯卡

1
再见,通过这种方法进行验证
Andre Elrico,

@Renan我正在使用formControl
Emir Herrera

29

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

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


5
“ arr.controls = [];” 提及真的很棒!
dotNetkow

@Pian,仅const arr = <FormArray> this.myForm.controls.arr; arr.controls = []; 正在清除表单数组。TQ
chandoo '18

inFormArray.at(1).remove(); 给我一个[ts] Property 'remove' does not exist on type 'AbstractControl'.翻译错误。
zgue

您模板中的@ Pian0_M4nlet c of inFormArray应该是let c of inFormArray.controls
沃尔玛

22

从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+。
帕特里克·希尔特

10

角度8

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

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


8

警告!

Angular v6.1.7 FormArray文档说:

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

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

使用removeAt功能。

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

6

您可以轻松地为数组定义一个吸气剂,并按以下步骤清除它:

  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()
  }

Thx它的工作原理……
nos nart

5

更新:Angular 8终于有了方法来清除Array FormArray.clear()




3

提供了将要用匹配项替换数组中信息的数据结构 patchValue

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

patchValue(值:任何[],{onlySelf,发射事件} ?: {onlySelf ?:布尔值,发射事件?:布尔值}):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,glowEvent} ?: {onlySelf ?: boolean,glowEvent ?: 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'

是我的一些早期工作演示的分叉的Plunker演示,演示了每个方法的简单用法。


当然,这意味着您必须在阵列中具有完全相同数量的项目吗?
Simon_Weaver

2

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

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

作为formGroup的FormGroup的实例。


1

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

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

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


0

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

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


0

为了保持代码的清洁,我为使用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;
}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.