Angular material mat-error cannot show message

33,009

Solution 1

a mat-error only shows when a FormControl is invalid, but you have the validation on your formgroup. So in that case you need to use a ErrorStateMatcher

In your case it would look like this:

export class MyErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    const invalidCtrl = !!(control && control.invalid);
    const invalidParent = !!(control && control.parent && control.parent.invalid);

    return (invalidCtrl || invalidParent);
  }
}

Also worth mentioning, it's not recommended to have two bindings, i.e formControl and ngModel. Remove the ngModel and utilize the form control instead. If you receive your start date and end date at a later point, you can use patchValue (just set some values to form) or setValue (set all values to form)

mark in component the errorstatematcher:

matcher = new MyErrorStateMatcher();

As for your custom validator, you don't need to parse the dates, just check if end date is smaller than start date:

checkDates(group: FormGroup) {
  if (group.controls.endDate.value < group.controls.startDate.value) {
    return { endDateLessThanStartDate: true }
  }
  return null;
}

and then mark the error state matcher in your template:

<mat-form-field>
  <input matInput [matDatepicker]="picker2" type="text" formControlName="endDate" [errorStateMatcher]="matcher">
  <mat-datepicker-toggle matSuffix [for]="picker2"></mat-datepicker-toggle>
  <mat-datepicker #picker2></mat-datepicker>
  <mat-error *ngIf="myForm.hasError('endDateLessThanStartDate')">End date cannot be earlier than start date</mat-error>
</mat-form-field>

Here's a StackBlitz

Solution 2

If you want to set a control as invalid from the .ts file manually...

HTML:

<mat-form-field class="full-width">
  <input matInput [formControl]="exampleFormControl" (change)="changeDetected()">
  <mat-hint>(Optional)</mat-hint>
  <mat-error *ngIf="exampleFormControl.hasError('invalid')">
      Must be a <strong>valid input</strong>!
  </mat-error>
</mat-form-field>

TS:

import { FormControl } from '@angular/forms';

@Component({
  selector: 'derp',
  templateUrl: './derp.html',
  styleUrls: ['./derp.scss'],
})
export class ExampleClass {

  // Date Error Form Control
  exampleFormControl = new FormControl('');

  // Variable Check
  inputValid: boolean;

  changeDetected() {
    // Check if input valid
    if (this.inputValid) {
      console.log('Valid Input');
    } else {
      console.log('Invalid Input');
      // IMPORTANT BIT - This makes the input invalid and resets after a form change is made
      this.exampleFormControl.setErrors({
        invalid: true,
      });
    }
  }

  // CODE THAT CHANGES VALUE OF 'inputValid' //

}
Share:
33,009
quoc bao Pham
Author by

quoc bao Pham

Updated on July 25, 2020

Comments

  • quoc bao Pham
    quoc bao Pham almost 4 years

    I have 2 datetime picker, endDate cannot be less than startDate

    endDateAfterOrEqualValidator(formGroup): any {
        var startDateTimestamp: number;
        var endDateTimestamp: number;
        startDateTimestamp = Date.parse(formGroup.controls['startDateForm'].value);
        endDateTimestamp = Date.parse(formGroup.controls['endDateForm'].value);
        return (endDateTimestamp < startDateTimestamp) ? { endDateLessThanStartDate: true } : null;
      }
    

    in html:

    <mat-form-field>
        <input matInput  name="endDate" id="endDate" formControlName="endDateForm" [(ngModel)]="endDate" [matDatepicker]="toDatePicker"
        placeholder="To Date">
        <mat-datepicker-toggle matSuffix [for]="toDatePicker"></mat-datepicker-toggle>
        <mat-datepicker disabled="false" #toDatePicker></mat-datepicker>
        <mat-error *ngIf="trainingDetail.hasError('endDateLessThanStartDate')">Not valid<mat-error>
    </mat-form-field>
    

    with "mat-error", the message does not display. I try to change by "small"

    <small *ngIf="trainingDetail.hasError('endDateLessThanStartDate')">Not valid</small>
    

    the message well. Please advice me how to using mat-error

  • quoc bao Pham
    quoc bao Pham over 6 years
    Thank you so much, it's good demo. But I change the End Date to the invalid date. this error message not display
  • AT82
    AT82 over 6 years
    What do you mean that you changed the end date to the invalid date? Could you demonstrate in the demo I made?
  • quoc bao Pham
    quoc bao Pham over 6 years
    Your default startDate in ts is 2017-11-25T22:00:00.000Z. But on UI display 11/26/2017 (maybe time zone). I try to change startDate first to 11/25/2017, and change invalid endDate. The error is displayed. Thanks
  • SatAj
    SatAj over 6 years
    @AJT_82 Is it possible to add "required" error state along with this custom validation? Thanks in adv.
  • Mohamad Mousheimish
    Mohamad Mousheimish almost 3 years
    I have a question here please, what's the use of form: FormGroupDirective in the isErrorState method. It's not used, so we can remove it right?