Search code examples
angularangular-material2angular6angular-material-6

Why mat-error not get displayed inside mat-form field in angular material 6 withcustom global validators


i am using angular material 6 ,i have a vaidation inside mat-form-field mat-error is not displayed , when move after mat-form-field to the mat-error which is displaying properly.

Not Working code:

 <mat-form-field>
<input matInput type="time" formControlName="ToTime"/> <mat-error *ngIf="DaterForm.get('ToTime').hasError('InValidToTime')">FromTime Should be less than ToTime if choose a same date</mat-error>
     </mat-form-field>

Working Fine:

 <input matInput type="time" formControlName="ToTime"/> </mat-form-field>
 <mat-error *ngIf="DaterForm.get('ToTime').hasError('InValidToTime')">FromTime Should be less than ToTime if choose a same date</mat-error>

Some one explain why which is not working inside that control.

Live Demo: stackblitz


Solution

  • Yes, mat-error does not show up by default. It only shows when the input is touched.

    But, luckily you can override this behavior using errorStateMatcher input property, bound to mat-input element.

    The pull request in which this feature was added.

    Usage :

    <mat-form-field>
        <input matInput [errorStateMatcher]="matcher" [matDatepicker]="picker" placeholder="Choose a Start date" 
        formControlName="FromDate"
          [min]="minFromDate" 
               [max]="maxToDate" >
        <mat-datepicker-toggle matSuffix [for]="picker" ></mat-datepicker-toggle>
        <mat-datepicker #picker></mat-datepicker>
        <mat-error >Please provide a valid Fromdate</mat-error> 
      </mat-form-field> 
    

    So you have to implement ErrorStateMatcher in your code this way.

    export class MyErrorStateMatcher implements ErrorStateMatcher {
      isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
        const isSubmitted = form && form.submitted;
        return (control && control.invalid);
      }
    }
    

    And in your component add a new object matcher for ErrorStateMatcher class, which will act as a value to [errorStateMatcher]="matcher"

    matcher = new MyErrorStateMatcher();
    

    I have also added the same code in your forked stackblitz

    Suggestion :

    You need not provide a ngIf condition for mat-error specifying your formControlName. It will be automatically considered based on the mat-form-field in which it is present.