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">