Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

angular - mat-error put to separate component not rendering properly

I want to use mat-errors to render server-side errors in my Angular 5 SPA.

This is what I've got so far, and it works

<mat-form-field class="col-6">
    <input matInput formControlName="firstName">
    <mat-error [hidden]="!form.controls.firstName.hasError('required')">This field is required and cannot be empty</mat-error>
    <mat-error [hidden]="!form.controls.firstName.hasError('other')">Some other error</mat-error>
</mat-form-field>

Every field of the form looks similar. Input field and many mat-error tags below. There is lots of repetitive code attached to single input field. Also, adding a new error message would cause adding it in the every field that needs it. I think it is a good space to introduce component that manages error messages, and injected with form control it decides which error to show (I want to have common error messages for all fields).

So I would like to have it this way

<mat-form-field class="col-6">
    <input matInput formControlName="firstName">
    <app-mat-errors [field]="form.controls.firstName"></app-map-errors>
</mat-form-field>

and in the app-mat-errors component template have all the mat-error code that we used to have in every single field

<mat-error [hidden]="!field.hasError('required')">This field is required and cannot be empty</mat-error>
<mat-error [hidden]="!field.hasError('other')">Some other error</mat-error>
etc....

With this approach I'm having a problem with rendering component correctly.

When put to the <app-mat-errors>, <mat-error> tags are embedded in app-mat-errors tag and are not showing properly (they are not styled and visible all the time, even when there is no error)

Is there any way angular can render component wihout parent tag? Or you have any ideas how to make it working properly? Thanks in advance.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The <mat-error> elements need to be direct children of <mat-form-field> in order to work properly, which is what you have discovered. So you can't wrap <mat-error> in another component and use that component inside <mat-form-field> in place of <mat-error>.

However, you don't need to have a one to one relationship between your errors and <mat-error> elements - <mat-error> is not a special object - it is just the container where <mat-form-field> displays error content. So you can put your error logic inside a component and use the component inside a single <mat-error> instead. Here's how that might look:

Form field HTML:

<mat-form-field class="col-6">
    <input matInput formControlName="firstName">
    <mat-error>
        <app-mat-errors [field]="form.controls.firstName"></app-map-errors>
    </mat-error>
</mat-form-field>

Errors component template:

<ng-container *ngIf="field.hasError('required')">This field is required and cannot be empty</ng-container>
<ng-container *ngIf="field.hasError('other')">Some other error</ng-container>
etc....

If your field can have more than one error, be sure to account for that in your *ngIf logic in order to avoid having more than one message appear.

You might also want to consider implementing the logic as a function rather than as a component, where it may be easier to write the logic:

<mat-form-field class="col-6">
    <input matInput formControlName="firstName">
    <mat-error>
        {{getErrorMessage(form.controls.firstName)}}
    </mat-error>
</mat-form-field>

getErrorMessage(control: FormControl): string {
    if (control) {
        if (control.hasError('required')) return 'This field is required and cannot be empty';
        if (control.hasError('other')) return 'Some other error';
        // etc.
    }
    return '';
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...