My form includes custom inputs and utilizes the ControlValueAccessor
. To view the implementation, visit this link. I encountered an issue where deleting an item from a FormArray
would inadvertently clear the values of the other FormGroups
still present in the array. An example scenario of this can be seen by adding media queries and deleting one after filling out another one. The code snippet below demonstrates how I have structured everything.
The form
SvgForm : FormGroup<SvgForm> = new FormGroup<SvgForm>({
title: new FormControl<string>(''),
graphicId: new FormControl<string>(''),
svgInput : new FormControl<string>(''),
viewBox : new FormGroup<ViewBoxParams>({
x: new FormControl<string>(''),
y: new FormControl<string>(''),
width: new FormControl<string>(''),
height: new FormControl<string>('')
}),
styling: new FormGroup<StylingParams>({
globalStyles: new FormControl<string>(''),
mediaQueries: new FormArray<FormGroup<MediaQueryParams>>([])
})
});
I pass the styling
FormGroup into a custom component called styling-input
in the template using an @Input()
like so
<styling-input [StylingForm]="SvgForm.controls.styling"></styling-input>
This is how the styling-input
is set up.
styling-input.component.ts
@Component({
selector: 'styling-input',
templateUrl: './styling-input.component.html',
styleUrls: ['./styling-input.component.css'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: StylingInputComponent,
multi: true
}
]
})
export class StylingInputComponent implements ControlValueAccessor{
@Input() StylingForm!: FormGroup<StylingParams>;
get MediaQueryList() {
return this.StylingForm.get('mediaQueries') as FormArray<FormGroup<MediaQueryParams>>;
}
writeValue(value: any){ if(value){ this.StylingForm.setValue(value); } }
registerOnChange(fn: any){ this.StylingForm.valueChanges.subscribe(fn); }
registerOnTouched(onTouched: Function){}
private createMediaQueryGroup(): FormGroup<MediaQueryParams> {
return new FormGroup<MediaQueryParams>({
selectorParams: new FormGroup<MediaSelectorParams>({
mediaType: new FormControl<MediaTypeParams>('all'),
expressions: new FormArray<FormGroup<MediaExpressionGroupParams>>([]),
}),
rules: new FormControl<string>('')
});
}
public addMediaQuery():void{
this.MediaQueryList.push(this.createMediaQueryGroup());
}
public removeMediaQuery(item: number): void{
this.MediaQueryList.removeAt(item);
}
}
Then in the template, I iterate over the MediaQueryList
getter like this
<article formArrayName="mediaQueries">
<media-query-input *ngFor="let a of MediaQueryList.controls; let i = index"
[MediaQueryForm]="a"
[attr.GroupId]="i"
(RemoveGroup)="removeMediaQuery($any($event))"
></media-query-input>
</article>
The MediaQueryForm
property is passed into the component as an @Input()
, and the i
variable is used to determine which group to remove when the delete button is clicked. The removeMediaQuery()
function utilizes removeAt()
on the MediaQueryList
.
I have not explored alternative solutions as the removal from a FormArray
is the suggested method. It is possible that interactions with the ControlValueAccessor
may be causing issues under the surface. If anyone has insights on why this issue occurs and how to resolve it, I would greatly appreciate it.