skip to Main Content

I want to add validations to mat-select where the user needs to select at least one entry

html file:

<mat-form-field>
  <mat-label>Select drink(s):</mat-label>
  <mat-select [formControl]="drinks" multiple (selectionChange)="checkSelectedDrinks($event.value)">
    @for (drink of drinkList; track drink) {
    <mat-option [value]="drink">{{drink}}</mat-option>
    }
  </mat-select>
  <mat-error *ngIf="drinkSelectionErr">
    You need to select at least one drink
  </mat-error>
</mat-form-field>

ts file:

drinkList: string[] = ["A","B","C","D","E"];

drinks = new FormControl(this.drinkList);

  checkSelectedDrinks(selectedDrinks: string[]){
    if (!selectedDrinks.length){
      this.drinkSelectionErr = true;
    }
  }

The code above does nothing when all drinks are unselected from the drop down menu.

3

Answers


  1. Chosen as BEST ANSWER

    I found the solution:

    For mat-error, I updated the 'if' condition to use the fromControl status attribute

     <mat-error *ngIf="drinks['status'] === 'INVALID'">
        You need to select at least one drink
      </mat-error>
    

  2. You are not setting any validators. Remove the onchange and add a validator.

    
    drinks = new FormControl(this.drinkList, (control) => {
      if (!control.value.length) {
         return {'must.select.item': true};
      }
      return null;
    });
    

    Then the control will be marked invalid when nothing is selected and you can display it in the HTML.

      <mat-error *ngIf="drinks.invalid">
        You need to select at least one drink
      </mat-error>
    

    Note that your validator could return multiple errors, in which case, you’d need to switch between possible error codes (must.select.item) to display the correct error message.

      <mat-error *ngIf="drinks.errors['must.select.item']">
        You need to select at least one drink
      </mat-error>
      <mat-error *ngIf="drinks.errors['something.else']">
        Another type of error.
    
    Login or Signup to reply.
  3. Here is a working example for your reference, we can just use the required validator of angular!

    ts

    import { Component } from '@angular/core';
    import { MatInputModule } from '@angular/material/input';
    import { MatFormFieldModule } from '@angular/material/form-field';
    import { MatSelectModule } from '@angular/material/select';
    import {
      FormControl,
      FormGroup,
      FormsModule,
      ReactiveFormsModule,
      Validators,
    } from '@angular/forms';
    import { CommonModule } from '@angular/common';
    
    /**
     * @title Basic Inputs
     */
    @Component({
      selector: 'input-overview-example',
      styleUrls: ['input-overview-example.css'],
      templateUrl: 'input-overview-example.html',
      standalone: true,
      imports: [
        FormsModule,
        MatFormFieldModule,
        MatInputModule,
        MatSelectModule,
        CommonModule,
        ReactiveFormsModule,
      ],
    })
    export class InputOverviewExample {
      drink = 'test';
      drinkList = ['test', 'test2', 'test3'];
      form = new FormGroup({
        drinks: new FormControl([this.drink], [Validators.required]),
      });
    }
    

    html

    <form [formGroup]="form">
      <mat-form-field>
        <mat-label>Select drink(s):</mat-label>
        <mat-select formControlName="drinks" multiple>
          @for (drink of drinkList; track drink) {
          <mat-option [value]="drink">{{drink}}</mat-option>
          }
        </mat-select>
        <mat-error *ngIf="form?.controls?.drinks?.errors?.required">
          You need to select at least one drink
        </mat-error>
      </mat-form-field>
    </form>
    

    stackblitz

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search