Home > Net >  How to validate form array with dynamic values using form builder
How to validate form array with dynamic values using form builder

Time:10-09

Am working on angular project where I need to submit a form with some values where the exams

form fields are dynamically created when I click the add button each row() will be added in the form.

for adding each exam values. I could delete each row as well in the form.

The requirement is I need to display a validation message for subject, mark and exams for each dynamic row created on click submit button if it is invalid/not selected. The exams field is a multiple checkbox list validate if nothing is selected

<form [formGroup] = "SettingsForm" (ngSubmit) = "SettingsFormSubmit()">
    <div class="row">
      <div class="col-xl-4">
        <input type="text" placeholder="Name" formControlName="Name">
      </div>
    <div class="row">
      <div class="col-xl-4 ">
        <p *ngIf="submitted && SettingsForm.get('Name').invalid class="text-danger">
          Name is required.
        </p>
      </div>
    </div>
    <div class="row">
      <div class="col-xl-12">
        <table class="table" formArrayName="PersonalData">
          <thead>
            <tr>
              <th>Subject</th>
              <th>Mark</th>
              <th>Exams</th>
              <th>Delete</th>
              <th><button type="button"  (click)="addPersonalData()" class="btn-blank">Add</button></th>
            </tr>
          </thead>
          <tbody>
            <tr [hidden]="!data.value.active"   *ngFor="let data of PersonalData().controls;let i=index" [formGroupName]="i">
              <td>
                <select class="form-control" formControlName="subject"  >
                  <option>Select Subject</option>
                  <ng-container *ngFor="let subject of subjects">
                  <option  value="{{ subject.id }}" >{{ subject.subject_name }}</option>
                  </ng-container>
                </select>
                <ng-container *ngIf="data.get(subject).invalid">
                  <span class="">error message</span>
                </ng-container>
              </td>
              <td>
                <select class="form-control" formControlName="mark">   
                  <option>Select Mark</option>
                  <option>50</option>
                  <option>60</option>
                  <option>90</option>
                </select>
                <ng-container *ngIf="data.get(mark).invalid">
                  <span class="">error message</span>
                </ng-container>
              </td>
              <td>
                <mat-form-field>
                  <mat-label>Select Exams</mat-label>
                  <mat-select  #examsSelect multiple formControlName="exams" >
                    <mat-option (click)="examsSelect()" *ngFor="let term of terms" [value]="term_id">
                      {{term.name}}
                    </mat-option>
                  </mat-select>
                </mat-form-field>
                  <ng-container *ngIf="data.get(exams).invalid">
                  <span class="">error message</span>
                </ng-container>
              </td>
              <td><button type="button"  (click)="deletedata(i)" >Delete</button>
              </td>
              <td><button type="button"  (click)="addPersonalData()" >Add</button>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
    <div class="modal-footer">
      <button type="submit" class="btn btn-success">Submit</button>
    </div>
   </form> 



   this.SettingsForm = this.formBuilder.group({
    id: [''], 
    Name: ['',Validators.required],
    PersonalData: this.formBuilder.array([this.formBuilder.control('', Validators.required)])
   });


  PersonalData() : FormArray {
    return this.SettingsForm.get("PersonalData") as FormArray
  }

  newPersonalData(): FormGroup {
    return this.formBuilder.group({
      id: '',
      subject: '',
      mark: '',
     exams: '',
   })
  }

  addPersonalData() {
    this.PersonalData().push(this.newPersonalData());
  }

Iam saving each PersonalData to the formbuilder dynamically so at a time suppose if I have added 3 rows added then a group of 3 form fields will be their as formarray with same formcontrolname how to validate and show error messages for all the dynamically generated form fields? I got error when I do so..

`ERROR TypeError: Cannot read properties of null (reading 'invalid')`

CodePudding user response:

You can call your formControlName.errors to check if there is an error in it directly in your html like so *ngIf="name.errors?.required" (for a Validators.required case). You can then display a message like: "This value is required".

It can also be called in the component.ts to validate forms before sending data.

Enjoy coding!

CodePudding user response:

Form initialized as

this.SettingsForm = this.formBuilder.group({
  id: [null],
  Name: [null, Validators.required],
  PersonalData: this.formBuilder.array([]),
});

Add validation for each dynamic field as

  newPersonalData(): FormGroup {
    return this.formBuilder.group({
      id: '',
      subject: [null, Validators.required],
      mark: [null, Validators.required],
      exams: [null, Validators.required],
    });
  }

There no field with name active so commented it

// [hidden]="!data.value.active"
<tr
*ngFor="let data of PersonalData().controls; let i = index"
[formGroupName]="i"
>

To do validation encode control name in inverted comma

<ng-container *ngIf="data.get('subject').invalid">

Sample Demo

  • Related