'How to set the default value group select in angular material

I am trying to get set a default value for the material.io form but I cant seem to get it working with the groups version. Here is my code

<mat-form-field>
  <mat-select placeholder="Pokemon" [formControl]="pokemonControl">
    <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>



selected = 'bulbasaur-0';

  pokemonGroups = [
    {
      name: 'Grass',
      pokemon: [
        { value: 'bulbasaur-0', viewValue: 'Bulbasaur' },
        { value: 'oddish-1', viewValue: 'Oddish' },
        { value: 'bellsprout-2', viewValue: 'Bellsprout' }
      ]
    },
    {
      name: 'Psychic',
      pokemon: [
        { value: 'mew-9', viewValue: 'Mew' },
        { value: 'mewtwo-10', viewValue: 'Mewtwo' },
      ]
    }
  ];


Solution 1:[1]

To set an option as selected, your select model must cope with the desired option.

Since you use reactive forms, try creating it like this :

this.myForm = this.fb.group({
  pokemonControl: this.pokemonGroups[0][0]
});

If you don't use a reactive form, then use this

pokemonControl: new FormControl(this.pokemonGroups[0][0]);

Solution 2:[2]

You are missing comparison function. Angular does not simply know how to select it. Accordingly to documentation compareWith - Function to compare the option values with the selected values. The first argument is a value from an option. The second is a value from the selection. A boolean should be returned. docs link

So regarding your implementation HTML

<mat-form-field>
  <mat-select placeholder="Pokemon" [formControl]="pokemonControl" [compareWith]="compareWith">
     <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>

TS

ngOnInit() {
    this.pokemonControl.setValue(this.selected);
  }

compareWith = (a: unknown, b: unknown): boolean => {
    return a == b;
  };

PS. In case your option value is an object then you can simply create a more complex comparator to display values.

IN YOUR CASE: To compare such complex objects with array types I would implement a life hack solution by stringifying the object. Simple and efficient.

compareWith = (a: YourType, b: YourType): boolean => {
    if (!a || !b) return false;
    return JSON.stringify(a) === JSON.stringify(b);
  };

Solution 3:[3]

I found this solution to your question.

The Angular Select documentation use two-way binding for value attribute for simple mat-select and mat-option ... But with mat-optgroup is not working, so you would better use NgModel binding.

HTML:

**<**mat-form-field>
  <mat-select placeholder="Pokemon" [formControl]="pokemonControl" [(ngModel)]="selected">
   <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>

TS:

selected: string = 'squirtle-3';

UPDATE:

The above will be working for Angular 6, and you will give a warning.

It looks like you're using ngModel on the same form field as formControlName. Support for using the ngModel input property and ngModelChange event with reactive form directives has been deprecated in Angular v6 and will be removed in Angular v7.

So you should use FormControl and use setValue link method in your case:

ngOnInit() {
    this.pokemonControl.setValue(this.selected);
  }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Alexander Golovinov
Solution 3