I have a parent form that contains a formArray which can I dynamically append additional formGroups to on click of a button that calls addForm()
:
ngOnInit() {
this.signupForm = this.formBuilder.group({
formList: this.formBuilder.array([this.formListGroupDef()]),
});
}
formListGroupDef() {
return this.formBuilder.control(
{
firstName: '',
email: '',
},
Validators.required
);
}
// Triggered on click of a button in the HTML
addForm() {
this.formList.push(this.formBuilder.control({ firstName: '', email: '' }));
}
In the parent form template, I iterate through the formArray and render them using the nested sub-form app-profile-form
that implements ControlValueAccessor
<ng-container formArrayName="formList">
<div *ngFor="let fg of formList.controls; let infoIndex = index">
<app-profile-form
[formControlName]="infoIndex"
[formIndex]="infoIndex"
></app-profile-form>
</div>
</ng-container>
app-profile-form
template:
<div [formGroup]="form">
<label for="first-name">First Name</label>
<input formControlName="firstName" id="first-name" />
<div *ngIf="firstNameControl.touched && firstNameControl.hasError('required')" class="error">
First Name is required
</div>
<label for="email">Email</label>
<input formControlName="email" type="email" id="email" />
<div *ngIf="emailControl.touched && emailControl.hasError('required')" class="error">
Email is required
</div>
<!-- delete the sub-form on click of this button and update the formList array in the parent form -->
<button name="deleteForm" (click)="delete()">Delete Form</button>
</div>
As the sub-form can be used on different parent forms, I need to be able to delete the sub-form within itself on the click of the deleteForm
button and update the formList array in the parent form. How can I achieve this?
Here's my stackblitz example. I need to implement the delete()
function in profile-form.component.ts
You can have nice work with DI
here, which is the power of Angular. So, just inject NgControl
and get its parent. Here is the solution:
profile-form.component.ts
...
constructor(private formBuilder: FormBuilder, private injector: Injector)
...
delete() {
// get the current NgControl directive here
const controlName = this.injector.get(NgControl);
// get the current FormArrayName directive here and get its control
const formArray = this.injector.get(FormArrayName).control;
// find the index, if your control exists in the FormArray
const index = formArray.controls.findIndex((control: AbstractControl) => control === controlName.control);
// and what you actually need to do
if (index > -1) {
formArray.removeAt(index);
}
}