1
votes

I am creating a form using reactive forms and angular material mat-select with multiple selection enabled. I have a list of objects to be loaded in the mat select and want to pre select some items in that list by default.

default selection is working well with strings (soda in the below example) and the default items are being shown with checked icon and the mat select element value has them loaded and if i add more items they get added to the existing items in value field.

but the items i want load in the mat select are objects (energyDrinks in the below example) and when I set the value for mat select field it does not check them by default even though the field value is being set properly. also if I add a item the existing data in the value field is getting overridden with the new items.

Is there any way I can get the pre selected items checked in UI select box and have the newly added items added the existing value of the mat-select element?

Thanks in advance

below is the sample code -

html -

<form [formGroup]="drinkCategory">

<mat-form-field class="full-width">
    <mat-select multiple formControlName="sodaName">
        <mat-option *ngFor="let soda of sodaList" [value]="soda">
            {{soda}}
        </mat-option>
    </mat-select>
</mat-form-field>

<p>{{drinkCategory.get('sodaName').value | json}}</p>


<mat-form-field class="full-width">
    <mat-select multiple formControlName="energyDrinkName">
        <mat-option *ngFor="let energyDrink of energyDrinksList" [value]="energyDrink">
            {{energyDrink.name}}
        </mat-option>
    </mat-select>
</mat-form-field>

<p>{{drinkCategory.get('energyDrinkName').value | json}}</p>
</form>

ts file -

import { Component , ViewChild} from '@angular/core';
import { FormBuilder, FormGroup,FormControl,Validators } from '@angular/forms';

@Component({
  selector: 'drink-example',
  styleUrls: ['drink-example.css'],
  templateUrl: 'drink-example.html',
})
export class DrinkExample {
  drinkCategory: FormGroup;

sodaList =['coke','pepsi','sprite'];
selecteSodas =['coke','sprite'];

  energyDrinksList=[{
    id:'1',
    name:'redbull'
  },{
    id:'2',
    name:'monster'
  },{
    id:'3',
    name:'gatorade'
  }];
   selectedEnergyDrinks=[{
      id:'1',
    name:'redbull'
  }];

  constructor(private fb: FormBuilder){}

  ngOnInit() {

        this.drinkCategory = this.fb.group({
            sodaName: [null, Validators.required],
      energyDrinkName:[null, Validators.required]
        });
      this.drinkCategory.get('sodaName').setValue(this.selecteSodas);
      this.drinkCategory.get('energyDrinkName').setValue(this.selectedEnergyDrinks);
    }
}

UI Screenshot of the mat select elements

1
can you please create a stackblitz for your issue.Jasdeep Singh

1 Answers

4
votes

You need to use a compareWith function to compare the options by id.

Add the function to the component:

compareWith(drink1: any, drink2: any): boolean {
 return drink1 && drink2 && drink1.id === drink2.id;
}

and then set it as the compareWith value on both the MatSelect controls:

 <form [formGroup]="drinkCategory">
  <mat-form-field class="full-width">
    <mat-select multiple formControlName="sodaName" [compareWith]="compareWith">
      <mat-option *ngFor="let soda of sodaList" [value]="soda">
        {{ soda }}
      </mat-option>
    </mat-select>
  </mat-form-field>

  <p>{{ drinkCategory.get('sodaName').value | json }}</p>

  <mat-form-field class="full-width">
    <mat-select
      multiple
      formControlName="energyDrinkName"
      [compareWith]="compareWith"
    >
      <mat-option
        *ngFor="let energyDrink of energyDrinksList"
        [value]="energyDrink"
      >
        {{ energyDrink.name }}
      </mat-option>
    </mat-select>
  </mat-form-field>

  <p>{{ drinkCategory.get('energyDrinkName').value | json }}</p>
</form>