I have a mat table in where Im getting values from backend and displaying. Now Im trying to add a new typeable field "cmnts", where it should be a text field and have validations. My issue here is validation is applying to every row & whatever text im entering in the first row , that is appearing in all the rows. Is my form control name should be unique for each row. In that case how should i use in ts file. Could you please suggest?
My html code is like below:
<table mat-table [dataSource]="dataSource" class="" matSort >
<tbody>
<th><td>...</td></th>
<ng-container matColumnDef="cmts">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Comments
</th>
<form [formGroup]="commentsForm" >
<td mat-cell *matCellDef="let element">
<span *ngIf="element?.id=='321'">
<mat-form-field>
<input matInput id="cmnts" formControlName="cmnts" required>
<mat-error *ngIf="submitted || h.cmnts.errors || h.cmnts.touched">
<span *ngIf="h.cmnts.errors?.required">cmnts is Required</span>
</mat-error>
<mat-error *ngIf="submitted || h.cmnts.errors">
<span *ngIf="h.cmnts.errors?.minlength"> Minimum length should be 10</span>
</mat-error>
<mat-error *ngIf="submitted || h.cmnts.errors">
<span *ngIf="h.cmnts.errors?.maxlength"> Maximum length should be 30 </span>
</mat-error>
</mat-form-field>
</span>
</td>
</form>
</ng-container>
My Ts file :
commentsForm: FormGroup;
this.commentsForm = this.fb.group({
cmnts: ['', [Validators.required,Validators.minLength(10), Validators.maxLength(40)]],
})
get h() { return this.commentsForm.controls; }
I have tried using formArray as below also. still unable to set validations separtely for each row. Please suggest. //Updated
<form [formGroup]="CmntsForm" >
<td mat-cell *matCellDef="let element;let rowIndex = index">
<span *ngIf="element?.sts=='A'">
<mat-form-field>
<input matInput id="cmnts" formControlName="cmnts" required>
</mat-form-field>
</span>
</td>
ts:
this.CmntsForm = this.fb.group({
cmnts: this.fb.array( ['', [Validators.required,Validators.minLength(1), Validators.maxLength(30)]])
})
get cmnts(){
return this.CmntsForm.controls["cmnts"] as FormArray;
}
You need to configure form array of form group with own validation rules for each row. Here is an example with the latest version of angular hope it helps.
HTML:
<form [formGroup]="commentsForm">
<table formArrayName="usercomments" mat-table [dataSource]="dataSource">
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef> ID </th>
<td mat-cell *matCellDef="let item"> {{item.id}} </td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let item"> {{item.name}} </td>
</ng-container>
<ng-container matColumnDef="comment">
<th mat-header-cell *matHeaderCellDef> Comment </th>
<td mat-cell *matCellDef="let item; let rowIndex=index">
<div [formGroupName]="rowIndex">
<mat-form-field>
<input
placeholder="Enter comment"
formControlName="comment"
matInput
/>
<mat-error *ngIf="commentFormArray.controls[rowIndex].get('comment')?.hasError('required')">
Comment is required.
</mat-error>
</mat-form-field>
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<button mat-raised-button [disabled]="commentsForm.invalid">Submit</button>
</form>
TS:
export interface UserComment {
id: number;
name: string;
comment: string;
}
export class UserCommentsComponent implements OnInit {
displayedColumns: string[] = ['id', 'name', 'comment'];
dataSource: UserComment[] = [
{ id: 1, name: 'John', comment: ''},
{ id: 2, name: 'Abram', comment: ''}
];
commentsForm: FormGroup;
constructor(private fb: FormBuilder){}
ngOnInit() {
this.commentsForm = this.fb.group({
usercomments: this.fb.array(this.loadUserComment(this.dataSource))
});
}
get commentFormArray() : FormArray {
return this.commentsForm.controls["usercomments"] as FormArray
}
private loadUserComment(comments: UserComment[]): FormGroup [] {
return comments.map((item: UserComment) =>
this.createCommentFormGroup(item));
}
private createCommentFormGroup(item: UserComment) : FormGroup{
return new FormGroup({
name: new FormControl(item.name),
comment: new FormControl(item.comment, [Validators.required])})
}
}