angularangular-reactive-formsformbuilder

handling with multiple mat-errors


I have my error handling for mat-input like this

      <mat-form-field>
        <input formControlName="title" matInput placeholder="Title*" />
        <mat-error *ngIf="addNewForm.get('title').errors?.required">
          Can not be empty
        </mat-error>
        <mat-error *ngIf="addNewForm.get('title').errors?.minlength">
          Min length is 1 character
        </mat-error>
        <mat-error *ngIf="addNewForm.get('title').errors?.maxlength">
          Max length is 255 characters
        </mat-error>
      </mat-form-field>

      <mat-form-field>
        <input formControlName="name" matInput placeholder="Name*" />
        <mat-error *ngIf="addNewForm.get('name').errors?.required">
          Can not be empty
        </mat-error>
        <mat-error *ngIf="addNewForm.get('name').errors?.minlength">
          Min length is 1 character
        </mat-error>
        <mat-error *ngIf="addNewForm.get('name').errors?.maxlength">
          Max length is 255 characters
        </mat-error>
      </mat-form-field>

How to handle this directly in component, soo instead of writing all of this errors manually, check all in component and dynamically set errors, something like this

      <mat-form-field>
        <input formControlName="title" matInput placeholder="Title*" />
        <mat-error>{{ someError }}</mat-error>
      </mat-form-field>

      <mat-form-field>
        <input formControlName="name" matInput placeholder="Name*" />
        <mat-error>{{ someError }}</mat-error>
      </mat-form-field>

Here is component

this.addNewUserForm = this.formBuilder.group({
      title: [
        "",
        [
          Validators.required,
          Validators.minLength(1),
          Validators.maxLength(255),
          noWhitespaceValidator
        ]
      ],
      name: [
        "",
        [
          Validators.required,
          Validators.minLength(4),
          Validators.maxLength(255),
          noWhitespaceValidator
        ]
      ]
    });

Solution

  • You can write a getter function which returns simply the error message. Like this:

    get errorMessage(): string {
       const form: FormControl = (this.addNewUserForm.get('title') as FormControl);
       return form.hasError('required') ?
         'Required error message' :
         form.hasError('maxlength') ?
         'Max length error' : 
         form.hasError('minlength') ?
         'Min length error' :
         form.hasError('nowhitespaceerror') ?
         'No white space error' : '';
    }
    

    After this you simply use this method like a variable in template:

    <mat-error>{{ errorMessage }}</mat-error>
    

    Or a simple solution based on this example: here.

    export class InputErrorExample {
      constructor(private formBuilder: FormBuilder) {}
    
      errorMessages = {
        maxlength: 'max',
        minlength: 'min',
        email: 'email'
      };
    
      addNewUserForm = this.formBuilder.group({
          title: [
            "",
            [
              Validators.required,
              Validators.minLength(1),
              Validators.maxLength(255),
              Validators.email
              // noWhitespaceValidator
            ]
          ]
        });
    
      errors(ctrl: FormControl): string[] {
        return ctrl.errors ? Object.keys(ctrl.errors) : [];
      }
    }
    
    <form class="example-form">
      <mat-form-field class="example-full-width">
        <input matInput placeholder="Email" [formControl]="addNewUserForm.get('title')"
               [errorStateMatcher]="matcher">
        <mat-hint>Errors appear instantly!</mat-hint>
        <mat-error>
          <ng-container *ngFor="let error of errors(addNewUserForm.get('title'))">
            {{ errorMessages[error] }} <br>
          </ng-container>
        </mat-error>
      </mat-form-field>
    </form>