Add replaceControls method to FormArray class
See original GitHub issue🚀 feature request
Relevant Package
This feature request is for the FormArray class in @angular/form.,
Description
Currently if i use a FormArray in a custom ControlValueAccessor i have to manually remove/add controls based on the writeValues input.
Here is an example:
import { Component, forwardRef, OnDestroy } from '@angular/core';
import { ControlValueAccessor, FormArray, FormControl, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Observable, ReplaySubject, Subscription } from 'rxjs';
import { filter, map, takeUntil } from 'rxjs/operators';
@Component({
template: `custom-value-accessor-template`,
selector: 'my-custom-value-accessor',
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => MyCustomControlValueAccessor),
multi: true
}]
})
export class MyCustomControlValueAccessor<TValue extends unknown = unknown> implements ControlValueAccessor,
OnDestroy {
protected readonly control = new FormArray([]);
protected readonly userValueChanges$: Observable<TValue[]>;
protected readonly destroyed = new ReplaySubject<void>(1);
private changesSubscription: Subscription | undefined;
private pauseChanges = false;
private _changeFn: (change: TValue[]) => void;
private _touchedFn: () => void;
constructor() {
this.userValueChanges$ = this.control.valueChanges.pipe(
filter(() => !this.pauseChanges),
map(() => this.control.getRawValue())
);
}
public writeValue(value: TValue[]): void {
this.pauseChanges = true;
while (this.control.length > 0) {
this.control.removeAt(0);
}
value.forEach(item => {
this.control.push(new FormControl(item));
});
this.pauseChanges = false;
}
public ngOnDestroy(): void {
this.destroyed.next();
this.destroyed.complete();
}
public registerOnChange(fn: (change: TValue[]) => void): void {
this._changeFn = fn;
if (!this.changesSubscription) {
this.userValueChanges$.pipe(
takeUntil(this.destroyed)
).subscribe(
val => this.change(val)
);
}
}
public registerOnTouched(fn: any): void {
this.touched = fn;
}
public change(value: TValue[]): void {
if (this._changeFn) this._changeFn(value);
}
public touched(): void {
if (this._touchedFn) this._touchedFn();
}
}
Describe the solution you’d like
It would be nice if the FormArray would implement a replaceControls method:
/**
* Replace the current controls with new ones.
*
* @usageNotes
* ### Replace controls of a FormArray
*
* ```typescript
* const arr = new FormArray([
* new FormControl(0),
* new FormControl(1),
* new FormControl(2)
* ]);
*
* console.log(arr.value); // [1, 2, 0]
*
* arr.replaceControls([new FormControl(2)]);
*
* console.log(arr.value); // [2]
* ```
*
* @param controls The new controls which will replace the old ones
*/
public replaceControls(controls: AbstractControl[]): void {
if(this.controls.length) {
this.controls.forEach(control => (control as any)._registerOnCollectionChange(() => undefined));
this.controls.splice(0);
}
controls.forEach(control => {
this.controls.push(control);
(this as any)._registerControl(control);
});
this.updateValueAndValidity();
(this as any)._onCollectionChange();
}
Issue Analytics
- State:
- Created 4 years ago
- Reactions:7
- Comments:6 (3 by maintainers)
Top Results From Across the Web
How to update controls of FormArray - angular - Stack Overflow
AFAIK putting a FormGroup inside of a FormArray strips the 'FormControls' of their names and makes it just a list, like a normal...
Read more >Add/Push and Remove Form fields dynamically to FormArray ...
We use the getter method to get us demoArray as FormArray directly from demoForm. It creates the new property named as demoArray so...
Read more >angular dynamic add form group - You.com | The AI Search ...
Create your FormGroup containing a FormArray. this.formGroup = new FormGroup({ licenses: new FormArray([]) }) · After receiving the data, store it into an...
Read more >FormArray - Angular
To change the controls in the array, use the push , insert , removeAt or clear methods in FormArray itself. These methods ensure...
Read more >Angular 2: Can't add form group to form array in reactive Forms
import {Component, OnInit} from '@angular/core'; import {FormGroup, FormBuilder, FormArray, Validators, FormControl} from "@angular/forms"; export class ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found

Glad I’m not the only one wanting this. ha!
This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.