How can I properly display <mat-error>
in a container without breaking the layout?
The background is this: I use a lot of basic validators in my template driven forms (required
, minlength
, pattern) and want to display the corresponding error message.
mat-form-fieldonly supports the display of one
mat-error` at a time, and for every message I need to display a human readable error message. So every input will look something like this:
<mat-form-field>
<input matInput required minlength="4" pattern="…">
<mat-error *ngIf="field?.errors?.required">Field is required</mat-error>
<mat-error *ngIf="field?.errors?.minlength">Must be at least {{ field!.errors!.minlength.requiredLength }} characters</mat-error>
<mat-error *ngIf="field?.errors?.pattern">Does not match pattern {{ … }}</mat-error>
</mat-form-field>
I have to do this for every field. Seems pretty redundant!
I have tried several approaches for extracting this pattern from the template:
*ngFor
<ng-container>
<ng-template>
However, they all mess up the layout, the error is then sort of displayed within the input field. I assume the issue is that mat-error
needs to be a direct descendant of mat-form-field
and all my approaches add an extra element between mat-error
and mat-form-field
.
So how can I handle errors without having to write all the mat-error
lines for every input?
I see that you are using the template driven approach, I tend to go for the Reactive one for any forms that don't class as really simple.
The method used should be made generic, passing in the field. I have used a single use-case for clarity
Typescript class:
get email() {
return this.form.get('email');
}
getEmailError() {
return this.email.hasError('required') ? 'You must enter an email address' :
this.email.hasError('email') ? 'Not a valid email' : '';
}
Template file:
<mat-form-field>
<input
type="email"
matInput
placeholder="Your Email"
autocomplete="false"
formControlName="email">
<mat-hint>Please enter an email address</mat-hint>
<mat-error *ngIf="email.invalid">{{getEmailError()}}</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput required minlength="4" pattern="…">
<mat-error *ngfor="let type of (validationTypes$ | async)">
<mat-error *ngIf="field?.errors[type]">{{validationMessagesService.getValidatorErrorMessage(type, maxLength, 'fieldName')}}</mat-error>
</mat-error>
</mat-form-field>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With