Angular Material - show mat-error on button click

2020-05-30 04:18发布

I am trying to do validation using the <mat-for-field> and <mat-error>. This works fine when user tabs out of the input without filling. But how do I force this error to show when I click a button? I am not using submit. Also, using template-driven forms.

This is my code:

HTML:

<mat-form-field>
    <input matInput placeholder="Due Date" name="dueDate" [(ngModel)]="dueDate" [formControl]="dueDateValidator" required>
    <mat-error *ngIf="dueDateValidator.invalid">Due Date is required for Tasks</mat-error>
</mat-form-field>

TS:

dueDateValidator: FormControl = new FormControl('', [Validators.required]);

9条回答
走好不送
2楼-- · 2020-05-30 04:29

This works for me. :) On button's click:

this.nameControl.markAsTouched();
查看更多
小情绪 Triste *
3楼-- · 2020-05-30 04:29

Based on Kyle Pfromer's post, I found my solution (to the same problem):

In the TS file I added the StateMatcher after I found an invalid form, eg.

if (this.myFormGroup.invalid) {
  this.matcher = new MyErrorStateMatcher();
  return;
}

In the MyErrorStateMatcher class I changed as following:

    return !!(control && control.invalid);

I find it confusing that Angular Material is not detecting the error anyway.

查看更多
甜甜的少女心
4楼-- · 2020-05-30 04:30

I am providing 3 different solutions for different scenarios, use the one which suits you.

  • If you are using a form, then do

    this.form.markAllAsTouched();
    
  • If you need a particular field to be affected inside form, then filter that nameControl and do

    nameControl.markAsTouched();
    
  • If you are not using forms, then specify a ref for the input element and initialize variable in ts file & do as follows,

    @ViewChild('myInputRef') myInputRef; // Initialize the ref of input element
    .
    .
    this.myInputRef.control.markAsTouched()
    
查看更多
Anthone
5楼-- · 2020-05-30 04:40

Since you want to show mat error on button's click, please try the below: For Angular6 version:

1). import below:
    import { FormControl, FormBuilder, FormGroup } from '@angular/forms';

2). declare form control in .ts file:
    nameControl = new FormControl('');

3). put control in html:
    <mat-form-field  style="width: 100%" floatPlaceholder="never">
      <input matInput placeholder="your placeholder text" [formControl]="nameControl" 
        required/>
      <mat-error *ngIf="nameControl.errors?.required">name is required</mat-error>
    </mat-form-field>

3). on button's click:
    this.nameControl.markAsTouched();

It's important to check how you are using the form control, ".markAsTouched()" on point 3 will show the mat error for the corresponding form control.

查看更多
叼着烟拽天下
6楼-- · 2020-05-30 04:42

You can also easily call the AbstractControl.updateValueAndValidity() function on button click. This will run the validation process on the corresponding ForControl again and show errors, if there are some (based on your Validators).

So, in your example:

    checkForErrorsOnButtonClick(): void {
      dueDateValidator.updateValueAndValidity();
    }
查看更多
Emotional °昔
7楼-- · 2020-05-30 04:43

See how to use a form with a custom ErrorStateMatcher

If you wish to override this behavior (e.g. to show the error as soon as the invalid control is dirty or when a parent form group is invalid), you can use the errorStateMatcher property of the matInput. The property takes an instance of an ErrorStateMatcher object. An ErrorStateMatcher must implement a single method isErrorState which takes the FormControl for this matInput as well as the parent form and returns a boolean indicating whether errors should be shown. (true indicating that they should be shown, and false indicating that they should not.)

I would make a separate file such as default.error-matcher.ts

/** Error when invalid control is dirty or touched*/
export class MyErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    return !!(control && control.invalid && (control.dirty || control.touched));
  }
}

Then in the TS file add:

matcher = new MyErrorStateMatcher();

Then change the input to use matcher:

<mat-form-field>
    <input matInput placeholder="Due Date" name="dueDate" [(ngModel)]="dueDate" [formControl]="dueDateValidator" [errorStateMatcher]="matcher" required>
    <mat-error *ngIf="dueDateValidator.invalid">Due Date is required for Tasks</mat-error>
</mat-form-field>
查看更多
登录 后发表回答