Angular Material Select

<mat-select> is a form control used for selecting a value from a set of options. It is same as the original <select> element. We will discuss more about the selections in Material Design Imagination.

To add selection options, add <mat-select> elements to <mat-select>. Angular content supports the use of <mat-form-field> inside the native <select> element. Add the matNativeControl attribute to the <select> element to use a parent selection inside <mat-form-field>.

app.component.html

  <h4>Basic mat-select</h4>  

<mat-form-field appearance="fill">  

  <mat-label>Favorite food</mat-label>  

  <mat-select>  

    <mat-option *ngFor="let food of foods" [value]="food.value">  

      {{food.viewValue}}  

    </mat-option>  

  </mat-select>  

</mat-form-field>  

<h4>Basic native select</h4>  

<mat-form-field appearance="fill">  

  <mat-label>Cars</mat-label>  

  <select matNativeControl required>  

    <option value="volvo">Volvo</option>  

    <option value="saab">Saab</option>  

    <option value="mercedes">Mercedes</option>  

    <option value="audi">Audi</option>  

  </select>  

</mat-form-field>  

    app.component.ts

    import {Component} from '@angular/core';  
    
      
    
    interface Food {  
    
      value: string;  
    
      viewValue: string;  
    
    }  
    
      
    
    /** 
    
     * @title Basic select 
    
     */  
    
    @Component({  
    
      selector: 'select-overview-example',  
    
      templateUrl: 'select-overview-example.html',  
    
    })  
    
    export class SelectOverviewExample {  
    
      foods: Food[] = [  
    
        {value: 'steak-0', viewValue: 'Steak'},  
    
        {value: 'pizza-1', viewValue: 'Pizza'},  
    
        {value: 'tacos-2', viewValue: 'Tacos'}  
    
      ];  
    
    }  

      Output:

      Angular Material Select

      Getting and setting the select value

      The <mat-select> supports 2-way binding to the value property without the need for Angular forms.

      app.component.html

       <mat-form-field appearance="fill">  
      
        <mat-label>Select an option</mat-label>  
      
        <mat-select [(value)]="selected">  
      
          <mat-option>None</mat-option>  
      
          <mat-option value="option1">Option 1</mat-option>  
      
          <mat-option value="option2">Option 2</mat-option>  
      
          <mat-option value="option3">Option 3</mat-option>  
      
        </mat-select>  
      
      </mat-form-field>  
      
      <p>You selected: {{selected}}</p> 

        app.component.ts

          import {Component} from '@angular/core';  
        
        /** @title Select with 2-way value binding */  
        
        @Component({  
        
          selector: 'select-value-binding-example',  
        
          templateUrl: 'select-value-binding-example.html',  
        
        })  
        
        export class SelectValueBindingExample {  
        
          selected = 'option2';  

          Output:

          Angular Material Select

          Both <mat-select> and <select> support Formsmodule (NgModel) and ReactiveFormsModule (FormControl, FormGroup, etc.).

          app.component.html

           <form>  
          
            <h4>mat-select</h4>  
          
            <mat-form-field appearance="fill">  
          
              <mat-label>Favorite food</mat-label>  
          
              <mat-select [(ngModel)]="selectedValue" name="food">  
          
                <mat-option *ngFor="let food of foods" [value]="food.value">  
          
                  {{food.viewValue}}  
          
                </mat-option>  
          
              </mat-select>  
          
            </mat-form-field>  
          
            <p> Selected food: {{selectedValue}} </p>  
          
            <h4>native html select</h4>  
          
            <mat-form-field appearance="fill">  
          
              <mat-label>Favorite car</mat-label>  
          
              <select matNativeControl [(ngModel)]="selectedCar" name="car">  
          
                <option value="" selected></option>  
          
                <option *ngFor="let car of cars" [value]="car.value">  
          
                  {{car.viewValue}}  
          
                </option>  
          
              </select>  
          
            </mat-form-field>  
          
            <p> Selected car: {{selectedCar}} </p>  
          
          </form> 

            app.component.ts

            import {Component} from '@angular/core';  
            
              
            
            interface Food {  
            
              value: string;  
            
              viewValue: string;  
            
            }  
            
              
            
            interface Car {  
            
              value: string;  
            
              viewValue: string;  
            
            }  
            
              
            
            /**  
            
             * @title Select in a form  
            
             */  
            
            @Component({  
            
              selector: 'select-form-example',  
            
              templateUrl: 'select-form-example.html',  
            
            })  
            
            export class SelectFormExample {  
            
              selectedValue: string;  
            
              selectedCar: string;  
            
              
            
              foods: Food[] = [  
            
                {value: 'steak-0', viewValue: 'Steak'},  
            
                {value: 'pizza-1', viewValue: 'Pizza'},  
            
                {value: 'tacos-2', viewValue: 'Tacos'}  
            
              ];  
            
              
            
              cars: Car[] = [  
            
                {value: 'volvo', viewValue: 'Volvo'},  
            
                {value: 'saab', viewValue: 'Saab'},  
            
                {value: 'mercedes', viewValue: 'Mercedes'}  
            
              ];  
            
            }

            Output:

            Angular Material Select

            Form field Features

            There are a number of <mat-form-field> features that are used with both <select> and <mat-select>. It includes error messages, prefixes, hint text and suffixes.

            app.component.html

            <h5>mat select</h5>  
            
            <mat-form-field appearance="fill">  
            
              <mat-label>Favorite animal</mat-label>  
            
              <mat-select [formControl]="animalControl" required>  
            
                <mat-option>--</mat-option>  
            
                <mat-option *ngFor="let animal of animals" [value]="animal">  
            
                  {{animal.name}}  
            
                </mat-option>  
            
              </mat-select>  
            
              <mat-error *ngIf="animalControl.hasError('required')">Please choose an animal</mat-error>  
            
              <mat-hint>{{animalControl.value?.sound}}</mat-hint>  
            
            </mat-form-field>  
            
            <h4>native html select</h4>  
            
            <mat-form-field appearance="fill">  
            
              <mat-label>Select your car (required)</mat-label>  
            
              <select matNativeControl required [formControl]="selectFormControl">  
            
                <option label="--select something --"></option>  
            
                <option value="saab">Saab</option>  
            
                <option value="mercedes">Mercedes</option>  
            
                <option value="audi">Audi</option>  
            
              </select>  
            
              <mat-error *ngIf="selectFormControl.hasError('required')">  
            
                This field is required  
            
              </mat-error>  
            
              <mat-hint>You can pick up your favorite car here</mat-hint>  
            
            </mat-form-field> 

              app.component.ts

              import {Component} from '@angular/core';  
              
              import {FormControl, Validators} from '@angular/forms';  
              
                
              
              interface Animal {  
              
                name: string;  
              
                sound: string;  
              
              }  
              
                
              
              /** @title Select with form field features */  
              
              @Component({  
              
                selector: 'select-hint-error-example',  
              
                templateUrl: 'select-hint-error-example.html',  
              
              })  
              
              export class SelectHintErrorExample {  
              
                animalControl = new FormControl('', Validators.required);  
              
                selectFormControl = new FormControl('', Validators.required);  
              
                animals: Animal[] = [  
              
                  {name: 'Dog', sound: 'Woof!'},  
              
                  {name: 'Cat', sound: 'Meow!'},  
              
                  {name: 'Cow', sound: 'Moo!'},  
              
                  {name: 'Fox', sound: 'Wa-pa-pa-pa-pa-pa-pow!'},  
              
                ];  
              
              }

              Output:

              Angular Material Select

              To set a static placeholder

              The placeholder is shown when the <mat-form-field> label is floating or the <mat-select> label is empty. It is used to give the user an additional indication about the value of their selection. The placeholder specifies by setting the placeholder attribute on the <mat-select> element. In some cases, that <mat-form-field> uses a placeholder as a label.

              Disabling the select or individual options

              We can disable the entire selection or individual options in a selection by using the Disable property on the <select> or <mat-select> and the <option> or <mat-option> elements.

              app.component.html

              <p>  
              
                <mat-checkbox [formControl]="disableSelect">Disable select</mat-checkbox>  
              
              </p>  
              
              <h4>mat-select</h4>  
              
              <mat-form-field appearance="fill">  
              
                <mat-label>Choose an option</mat-label>  
              
                <mat-select [disabled]="disableSelect.value">  
              
                  <mat-option value="option1">Option 1</mat-option>  
              
                  <mat-option value="option2" disabled>Option 2 (disabled)</mat-option>  
              
                  <mat-option value="option3">Option 3</mat-option>  
              
                </mat-select>  
              
              </mat-form-field>  
              
                
              
              <h4>native html select</h4>  
              
              <mat-form-field appearance="fill">  
              
                <mat-label>Choose an option</mat-label>  
              
                <select matNativeControl [disabled]="disableSelect.value">  
              
                  <option value="" selected></option>  
              
                  <option value="volvo">Volvo</option>  
              
                  <option value="saab" disabled>Saab</option>  
              
                  <option value="mercedes">Mercedes</option>  
              
                  <option value="audi">Audi</option>  
              
                </select>  
              
              </mat-form-field> 

                app.component.ts

                import {Component} from '@angular/core';  
                
                import {FormControl} from '@angular/forms';  
                
                  
                
                /** @title Disabled select */  
                
                @Component({  
                
                  selector: 'select-disabled-example',  
                
                  templateUrl: 'select-disabled-example.html',  
                
                })  
                
                export class SelectDisabledExample {  
                
                  disableSelect = new FormControl(false);  
                
                } 

                  Output:

                  Angular Material Select

                  Creating groups of options

                  The <mat-optgroup> element is used to group common options under a subheading. The group name will set by using the label property of <mat-optgroup>. Like individual <mat-options> elements, the whole <mat-Optgroup> can be disabled or enabled by setting the Disable property.

                  app.component.html

                  <h4>mat-select</h4>  
                  
                  <mat-form-field appearance="fill">  
                  
                    <mat-label>Pokemon</mat-label>  
                  
                    <mat-select [formControl]="pokemonControl">  
                  
                      <mat-option>-- None --</mat-option>  
                  
                      <mat-optgroup *ngFor="let group of pokemonGroups" [label]="group.name"  
                  
                                    [disabled]="group.disabled">  
                  
                        <mat-option *ngFor="let pokemon of group.pokemon" [value]="pokemon.value">  
                  
                          {{pokemon.viewValue}}  
                  
                        </mat-option>  
                  
                      </mat-optgroup>  
                  
                    </mat-select>  
                  
                  </mat-form-field>  
                  
                    
                  
                  <h4>native html select</h4>  
                  
                  <mat-form-field appearance="fill">  
                  
                    <mat-label>Cars</mat-label>  
                  
                    <select matNativeControl>  
                  
                      <optgroup label="Swedish Cars">  
                  
                        <option value="volvo">volvo</option>  
                  
                        <option value="saab">Saab</option>  
                  
                      </optgroup>  
                  
                      <optgroup label="German Cars">  
                  
                        <option value="mercedes">Mercedes</option>  
                  
                        <option value="audi">Audi</option>  
                  
                      </optgroup>  
                  
                    </select>  
                  
                  </mat-form-field>  

                    app.component.ts

                    import {Component} from '@angular/core';  
                    
                    import {FormControl} from '@angular/forms';  
                    
                      
                    
                    interface Pokemon {  
                    
                      value: string;  
                    
                      viewValue: string;  
                    
                    }  
                    
                      
                    
                    interface PokemonGroup {  
                    
                      disabled?: boolean;  
                    
                      name: string;  
                    
                      pokemon: Pokemon[];  
                    
                    }  
                    
                      
                    
                    /** @title Select with option groups */  
                    
                    @Component({  
                    
                      selector: 'select-optgroup-example',  
                    
                      templateUrl: 'select-optgroup-example.html',  
                    
                    })  
                    
                    export class SelectOptgroupExample {  
                    
                      pokemonControl = new FormControl();  
                    
                      pokemonGroups: PokemonGroup[] = [  
                    
                        {  
                    
                          name: 'Grass',  
                    
                          pokemon: [  
                    
                            {value: 'bulbasaur-0', viewValue: 'Bulbasaur'},  
                    
                            {value: 'oddish-1', viewValue: 'Oddish'},  
                    
                            {value: 'bellsprout-2', viewValue: 'Bellsprout'}  
                    
                          ]  
                    
                        },  
                    
                        {  
                    
                          name: 'Water',  
                    
                          pokemon: [  
                    
                            {value: 'squirtle-3', viewValue: 'Squirtle'},  
                    
                            {value: 'psyduck-4', viewValue: 'Psyduck'},  
                    
                            {value: 'horsea-5', viewValue: 'Horsea'}  
                    
                          ]  
                    
                        },  
                    
                        {  
                    
                          name: 'Fire',  
                    
                          disabled: true,  
                    
                          pokemon: [  
                    
                            {value: 'charmander-6', viewValue: 'Charmander'},  
                    
                            {value: 'vulpix-7', viewValue: 'Vulpix'},  
                    
                            {value: 'flareon-8', viewValue: 'Flareon'}  
                    
                          ]  
                    
                        },  
                    
                        {  
                    
                          name: 'Psychic',  
                    
                          pokemon: [  
                    
                            {value: 'mew-9', viewValue: 'Mew'},  
                    
                            {value: 'mewtwo-10', viewValue: 'Mewtwo'},  
                    
                          ]  
                    
                        }  
                    
                      ];  
                    
                    }

                    Output:

                    Angular Material Select

                    Multiple Selections

                    The <mat-select> defaults to single-select mode but can be configured to allow different classes by setting other properties. When using <mat-select> in multiple selection mode, its value will be a sorted list of all selected values instead of a single value.

                    app.component.html

                    <mat-form-field appearance="fill">  
                    
                      <mat-label>Toppings</mat-label>  
                    
                      <mat-select [formControl]="toppings" multiple>  
                    
                        <mat-option *ngFor="let topping of toppingList" [value]="topping">{{topping}}</mat-option>  
                    
                      </mat-select>  
                    
                    </mat-form-field> 

                      app.component.ts

                      import {Component} from '@angular/core';  
                      
                      import {FormControl} from '@angular/forms';  
                      
                        
                      
                      /** @title Select with multiple selection */  
                      
                      @Component({  
                      
                        selector: 'select-multiple-example',  
                      
                        templateUrl: 'select-multiple-example.html',  
                      
                      })  
                      
                      export class SelectMultipleExample {  
                      
                        toppings = new FormControl();  
                      
                        toppingList: string[] = ['Extra cheese', 'Mushroom', 'Onion', 'Pepperoni', 'Sausage', 'Tomato'];  
                      
                      } 

                        Output:

                        Angular Material Select

                        Customizing the trigger label

                        If you have to display a custom trigger label inside a <mat-select>, you can use <mat-select-trigger> element.

                        Disabling the ripple effect

                        When the user clicks on <mat-option> then the ripple animation is shown. It could disable by the disableRipple property on <mat-select>.

                        app.component.html

                        <mat-form-field appearance="fill">  
                        
                          <mat-label>Select an option</mat-label>  
                        
                          <mat-select disableRipple>  
                        
                            <mat-option value="1">Option 1</mat-option>  
                        
                            <mat-option value="2">Option 2</mat-option>  
                        
                            <mat-option value="3">Option 3</mat-option>  
                        
                          </mat-select>  
                        
                        </mat-form-field>  

                          app.component.ts

                          import {Component} from '@angular/core';  
                          
                          /** @title Select with no option ripple */  
                          
                          @Component({  
                          
                            selector: 'select-no-ripple-example',  
                          
                            templateUrl: 'select-no-ripple-example.html',  
                          
                          })  
                          
                          export class SelectNoRippleExample {}  

                            Output:

                            Angular Material Select

                            Adding custom styles to the dropdown panel

                            To styling the dropdown panel,  has a panel Class property which is used to apply additional CSS classes to the dropdown panel.

                            app.component.html

                            <mat-form-field appearance="fill">  
                            
                              <mat-label>Panel color</mat-label>  
                            
                              <mat-select [formControl]="panelColor"  
                            
                                          panelClass="example-panel-{{panelColor.value}}">  
                            
                                <mat-option value="red">Red</mat-option>  
                            
                                <mat-option value="green">Green</mat-option>  
                            
                                <mat-option value="blue">Blue</mat-option>  
                            
                              </mat-select>  
                            
                            </mat-form-field>  

                              app.component.ts

                              import {Component, ViewEncapsulation} from '@angular/core';  
                              
                              import {FormControl} from '@angular/forms';  
                              
                                
                              
                              /**  
                              
                               * @title Select with custom panel styling  
                              
                               */  
                              
                              @Component({  
                              
                                selector: 'select-panel-class-example',  
                              
                                templateUrl: 'select-panel-class-example.html',  
                              
                                styleUrls: ['select-panel-class-example.css'],  
                              
                                // Encapsulation has to be disabled in order for the  
                              
                                // component style to apply to the select panel.  
                              
                                encapsulation: ViewEncapsulation.None,  
                              
                              })  
                              
                              export class SelectPanelClassExample {  
                              
                                panelColor = new FormControl('red');  
                              
                              }  

                                app.component.css

                                .example-panel-red.mat-select-panel {  
                                
                                  background: rgba(255, 0, 0, 0.5);  
                                
                                }  
                                
                                  
                                
                                .example-panel-green.mat-select-panel {  
                                
                                  background: rgba(0, 255, 0, 0.5);  
                                
                                }  
                                
                                  
                                
                                .example-panel-blue.mat-select-panel {  
                                
                                  background: rgba(0, 0, 255, 0.5);  
                                
                                }  

                                  Output:

                                  Angular Material Select

                                  Changing when error messages are shown

                                  The <mat-form-field> allows us to associate error messages with the <select> or <mat-select>. By default, error messages are came when the control is invalid or the user has interacted with the element. If we want to override the behavior, we can use the errorStateMatcher property <mat-select>. The property takes an instance of the ErrorStateMatcher object

                                  app.component.html

                                  <h4>mat-select</h4>  
                                  
                                  <mat-form-field appearance="fill">  
                                  
                                    <mat-label>Choose one</mat-label>  
                                  
                                    <mat-select [formControl]="selected" [errorStateMatcher]="matcher">  
                                  
                                      <mat-option>Clear</mat-option>  
                                  
                                      <mat-option value="valid">Valid option</mat-option>  
                                  
                                      <mat-option value="invalid">Invalid option</mat-option>  
                                  
                                    </mat-select>  
                                  
                                    <mat-hint>Errors appear instantly!</mat-hint>  
                                  
                                    <mat-error *ngIf="selected.hasError('required')">You must make a selection</mat-error>  
                                  
                                    <mat-error *ngIf="selected.hasError('pattern') && !selected.hasError('required')">  
                                  
                                      Your selection is invalid  
                                  
                                    </mat-error>  
                                  
                                  </mat-form-field>  
                                  
                                  <h4>native html select</h4>  
                                  
                                  <mat-form-field class="demo-full-width" appearance="fill">  
                                  
                                    <mat-label>Choose one</mat-label>  
                                  
                                    <select matNativeControl [formControl]="nativeSelectFormControl" [errorStateMatcher]="matcher">  
                                  
                                      <option value=""></option>  
                                  
                                      <option value="valid" selected>Valid option</option>  
                                  
                                      <option value="invalid">Invalid option</option>  
                                  
                                    </select>  
                                  
                                    <mat-error *ngIf="nativeSelectFormControl.hasError('required')">You must make a selection</mat-error>  
                                  
                                    <mat-error *ngIf="nativeSelectFormControl.hasError('pattern') && !nativeSelectFormControl.hasError('required')">  
                                  
                                      Your selection is invalid  
                                  
                                    </mat-error>  
                                  
                                  </mat-form-field>  

                                    app.component.ts

                                    import {Component} from '@angular/core';  
                                    
                                    import {FormControl, FormGroupDirective, NgForm, Validators} from '@angular/forms';  
                                    
                                    import {ErrorStateMatcher} from '@angular/material/core';  
                                    
                                      
                                    
                                    /** Error when invalid control is touched or submitted. */  
                                    
                                    export class MyErrorStateMatcher implements ErrorStateMatcher {  
                                    
                                      isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {  
                                    
                                        const isSubmitted = form && form.submitted;  
                                    
                                        return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted));  
                                    
                                      }  
                                    
                                    }  
                                    
                                    /** @title Select with a custom ErrorStateMatcher */  
                                    
                                    @Component({  
                                    
                                      selector: 'select-error-state-matcher-example',  
                                    
                                      templateUrl: 'select-error-state-matcher-example.html',  
                                    
                                    })  
                                    
                                    export class SelectErrorStateMatcherExample {  
                                    
                                      selected = new FormControl('valid', [  
                                    
                                        Validators.required,  
                                    
                                        Validators.pattern('valid'),  
                                    
                                      ]);  
                                    
                                      
                                    
                                      selectFormControl = new FormControl('valid', [  
                                    
                                        Validators.required,  
                                    
                                        Validators.pattern('valid'),  
                                    
                                      ]);  
                                    
                                      nativeSelectFormControl = new FormControl('valid', [  
                                    
                                        Validators.required,  
                                    
                                        Validators.pattern('valid'),  
                                    
                                      ]);  
                                    
                                      matcher = new MyErrorStateMatcher();  
                                    
                                    }

                                    Output:

                                    Angular Material Select

                                    A global error condition matching can be specified by setting the ErrorStateMatcher provider. It applies to all inputs. ShowOnDirtyErrorStateMatcher is available to show globally available input errors when the input is invalid.

                                    @NgModule({  
                                    
                                      providers: [  
                                    
                                        {provide: ErrorStateMatcher, useClass: ShowOnDirtyErrorStateMatcher}  
                                    
                                      ]  
                                    
                                    })  

                                      Keyboard interaction

                                      DOWN_ARROW: It focuses on the next option

                                      UP_ARROW: It focuses on the previous option

                                      ENTER or SPACE: It selects on the focused item

                                      Accessibility

                                      The <mat-select> component has “combobox”, the dropdown panel has “listbox” and options inside select panel have “option”.

                                      The native <select> offers the best accessibility, and screen-readers support it.

                                      Troubleshooting

                                      Error: Cannot change multiple modes of select after initialization

                                      It occurs if we try to bind different properties on the dynamic value to <mat-select>.

                                      <mat-select *ngIf="isMultiple" multiple>  
                                      
                                        ...  
                                      
                                      </mat-select>  
                                      
                                      <mat-select *ngIf="!isMultiple">  
                                      
                                        ...  
                                      
                                      </mat-select> 

                                        Error: Value is an array in multiple-selection mode

                                        It occurs when we assign a value other than null, undefined, or an array to the <mat-select multiple>.

                                        For example, mySelect.value = ‘option1’.


                                        Comments

                                        Leave a Reply

                                        Your email address will not be published. Required fields are marked *