Home > OS >  Angular Material: mat-error encapsulation
Angular Material: mat-error encapsulation

Time:11-09

I want to encapsulate the mat-error into its own component since the text tends to be quite long. Therefore I thought about:

<form [formGroup]="form">
    <mat-form-field>
        <input matInput formControlName="title" placeholder="Title" required />
        <app-mat-error-too-long [ctrl]="form.controls.title"></app-mat-error-too-long>
     </mat-form-field>
</form>

and

<mat-error *ngIf="ctrl.hasError('maxlength')">
    <span >Input too long</span>
    <span>&nbsp;</span>
    <span>{{ctrl.getError('maxlength').actualLength}}/{{ctrl.getError('maxlength').requiredLength}}</span>
</mat-error>  

with the component:

    import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
    import { AbstractControl } from '@angular/forms';
    
    @Component({
      selector: 'app-mat-error-too-long',
      templateUrl: './mat-error-too-long.component.html',
      styleUrls: ['./mat-error-too-long.component.scss'],
    })
    export class MatErrorTooLongComponent implements OnInit {
      @Input() ctrl: AbstractControl
    
      constructor() { }
    
      ngOnInit(): void {
      }
    
    }

But if I do so the error is not displayed properly and is right under the component:

enter image description here

CodePudding user response:

mat-error needs to be used directly inside mat-form-field to work correctly. So what you can do is to use an attribute selector instead for your child component and attach it to mat-error:

 <mat-form-field>
   <input matInput formControlName="title" placeholder="Title" required />
   <mat-error app-mat-error-too-long [ctrl]="form.controls.title"></mat-error>
 </mat-form-field>

Then you need to of course remove the mat-error tag from the child and instead just show your messages. The child selector also needs to change, wrap brackets around it:

selector: '[app-mat-error-too-long]'
  • Related