How to remove nested sub-form from the sub-form itself?

123 Views Asked by At

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

1

There are 1 best solutions below

1
Anton Marinenko On BEST ANSWER

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