I have a form array inside a formbuilder and i am dynamically changing forms, i.e. on click load data from application 1 etc.
The issue i am having is that all the
As of Angular 8+ you can use clear()
to remove all controls in the FormArray:
const arr = new FormArray([
new FormControl(),
new FormControl()
]);
console.log(arr.length); // 2
arr.clear();
console.log(arr.length); // 0
For previous versions the recommended way is:
while (arr.length) {
arr.removeAt(0);
}
https://angular.io/api/forms/FormArray#clear
You can easily define a getter for your array and clear it as follows:
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()
}
While loop will take long time to delete all items if array has 100's of items. You can empty both controls and value properties of FormArray like below.
clearFormArray = (formArray: FormArray) => { formArray.controls = []; formArray.setValue([]); }
Provided the data structure for what you will be replacing the information in the array with matches what is already there you can use 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 Patches the value of the FormArray. It accepts an array that matches the structure of the control, and will do its best to match the values to the correct controls in the group.
It accepts both super-sets and sub-sets of the array without throwing an error.
const arr = new FormArray([
new FormControl(),
new FormControl()
]);
console.log(arr.value); // [null, null]
arr.patchValue(['Nancy']);
console.log(arr.value); // ['Nancy', null]
Alternatively you could use reset
reset(value?: any, {onlySelf, emitEvent}?: {onlySelf?: boolean, emitEvent?: boolean}) : void Resets the FormArray. This means by default:
The array and all descendants are marked pristine The array and all descendants are marked untouched The value of all descendants will be null or null maps You can also reset to a specific form state by passing in an array of states that matches the structure of the control. The state can be a standalone value or a form state object with both a value and a disabled status.
this.arr.reset(['name', 'last name']);
console.log(this.arr.value); // ['name', 'last name']
OR
this.arr.reset([ {value: 'name', disabled: true}, 'last' ]);
console.log(this.arr.value); // ['name', 'last name']
console.log(this.arr.get(0).status); // 'DISABLED'
Here's a forked Plunker demo from some earlier work of mine demoing a very simple utilization of each.
To keep the code clean I have created the following extension method for anyone using Angular 7 and below. This can also be used to extend any other functionality of 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;
}
Warning!
The Angular v6.1.7 FormArray documentation says:
To change the controls in the array, use the push, insert, or removeAt methods in FormArray itself. These methods ensure the controls are properly tracked in the form's hierarchy. Do not modify the array of AbstractControls used to instantiate the FormArray directly, as that result in strange and unexpected behavior such as broken change detection.
Keep this in mind if you are using the splice
function directly on the controls
array as one of the answer suggested.
Use the removeAt
function.
while (formArray.length !== 0) {
formArray.removeAt(0)
}