I am working with Angular’s reactive forms and have a nested structure where I need to validate that a FormArray
of files within another FormArray
is not empty. Specifically, each groupFiles
can have multiple groups, and each group contains a FormArray
of files. I need to display a mat-error
message if any group’s files
array is empty.
My Form Structure
Here’s how I’ve set up my form:
import { FormBuilder, FormGroup, FormArray, Validators } from '@angular/forms';
export class MyComponent {
serviceRequestForm: FormGroup;
constructor(private fb: FormBuilder) {
this.serviceRequestForm = this.fb.group({
groupFiles: this.fb.array([])
});
}
get groupFiles(): FormArray {
return this.serviceRequestForm.get('groupFiles') as FormArray;
}
addGroupFile(groupFile: any) {
const fileControls = this.fb.array([
this.fb.group({
fileName: ['', Validators.required],
is_high: [false, Validators.required],
uploadFileName: '',
fileType: '',
fileBase64: '',
})
]);
const group = this.fb.group({
groupFileId: [groupFile.ID],
groupName: [groupFile.DISPLAY_DESCRIPTION, Validators.required],
orderNo: [groupFile.ORDER_NO, Validators.required],
files: fileControls
});
this.groupFiles.push(group);
}
removeGroupFile(index: number) {
this.groupFiles.removeAt(index);
}
}
The Template
I am trying to show an error if the files
array is empty using mat-error
:
<div formArrayName="groupFiles">
<div *ngFor="let groupFile of groupFiles.controls; let i = index" [formGroupName]="i">
<span class="col-sm-12">{{ i + 1 }}</span>
<mat-form-field style="width: 80%" appearance="outline">
<mat-label>Group Name</mat-label>
<input matInput type="text" formControlName="groupName" id="groupName" />
<mat-error *ngIf="groupFile.get('groupName')?.hasError('required')">
Field is required
</mat-error>
<mat-error *ngIf="groupFile.get('files')?.value?.length === 0">
Files are required for this group.
</mat-error>
<button mat-icon-button color="warn" type="button" matSuffix (click)="removeGroupFile(i)">
<mat-icon>delete</mat-icon>
</button>
</mat-form-field>
</div>
</div>
The Issue
The mat-error
for checking if the files
array is empty is not working as expected. The length check on files
does not seem to trigger the error display correctly. I have tried a few things, but none seem to work:
-
I tried adding a custom validator to check if the
files
array is empty. -
I tried using
.length === 0
directly in the template.
What I’ve Tried
- Custom Validator:
import { AbstractControl, ValidatorFn } from '@angular/forms';
export function filesNotEmptyValidator(): ValidatorFn {
return (formArray: AbstractControl) => {
const files = formArray.value;
return files && files.length > 0 ? null : { filesNotEmpty: true };
};
}
Applied like this:
const group = this.fb.group({
groupFileId: [groupFile.ID],
groupName: [groupFile.DISPLAY_DESCRIPTION, Validators.required],
orderNo: [groupFile.ORDER_NO, Validators.required],
files: this.fb.array(fileControls, filesNotEmptyValidator())
});
Template Length Check:
<mat-error *ngIf="groupFile.get('files')?.value?.length === 0">
Files are required for this group.
</mat-error>
What I Need
I want to validate that the files
FormArray
is not empty and show an error message using mat-error
if it is. How can I correctly implement this validation and ensure the error is displayed?