Update incluying services*
In general, in a mat-select multiple that is feeded whith an array of object we need take account two things
1.- the result (in a FormControl or in a variable using [(ngModel)]) is an array
2.- we general want to store in the variable or in the form control, one property of the object and show anohter
So, a tipical
toppingList: any[] = [
{id: 1, name: "John"},
{id: 2, name: "Marry"},
{id: 3, name: "Thomson"}];
need a getter
toppings = new FormControl();
get toppingsName()
{
return this.toppings.value?
this.toppingList.filter(t=>this.toppings.value.indexOf(t.id)>=0)
.map(x=>x.name):
null
}
If we has a service that return an array we can write
this.dataService.getToppings1().subscribe((res:number[])=>{
this.toppings.setValue(res)
})
<mat-form-field appearance="fill">
<mat-label>Toppings</mat-label>
<mat-select [formControl]="toppings" multiple>
<mat-select-trigger>
{{toppingsName}}
</mat-select-trigger>
<mat-option *ngFor="let topping of toppingList" [value]="topping.id">{{topping.name}}</mat-option>
</mat-select>
</mat-form-field>
Or using ngModel
value:any=null;
get toppingsNameValue()
{
return this.value?this.toppingList.filter(t=>this.value.indexOf(t.id)>=0).map(x=>x.name):null
}
If we has a service that return an string separate by commas with the toppings choose we can do -see that first make a spit, but we need transform this array of string in array of numbers-
this.dataService.getToppings2().subscribe((res:string)=>{
this.value=res.split(',').map(x=>+x)
})
<mat-form-field appearance="fill">
<mat-label>Toppings</mat-label>
<mat-select [(ngModel)]="value" multiple>
<mat-select-trigger>
{{toppingsNameValue}}
</mat-select-trigger>
<mat-option *ngFor="let topping of toppingList" [value]="topping.id">{{topping.name}}</mat-option>
</mat-select>
</mat-form-field>
Well, we can also that we want an array of object (it's not ussual, remember that always can get the value simply using this.toppingList.filter(t=>this.toppings.value.indexOf(t.id)>=0
We can do
toppingsObject = new FormControl();
get toppingsObjectName()
{
return this.toppingsObject.value?this.toppingsObject.value.map((x:any)=>x.name):null
}
Now, our service is going to return an array of object. But we can not use directly an object to feed our control. We need a "compare function". Its only a function that has two arguments. We return true if we considered the two object equals. Some like
compareFn(a:any,b:any){
if (a.id==b.id)
return true
else
return false
}
Well, normally we abreviature and write this function like
compareFn=(a:any,b:any)=>a.id==b.id
Now our subscription to the service is like
this.dataService.getToppings3().subscribe((res:any[])=>{
this.toppingsObject.setValue(res)
})
<mat-form-field appearance="fill">
<mat-label>Toppings</mat-label>
<!--see how use the compareFn-->
<mat-select [formControl]="toppingsObject" multiple [compareWith]="compareFn">
<mat-select-trigger>
{{toppingsObjectName}}
</mat-select-trigger>
<mat-option *ngFor="let topping of toppingList" [value]="topping">{{topping.name}}</mat-option>
</mat-select>
</mat-form-field>
See that in this case [value] is the own "topping"
NOTE: In general we store the data in a dbs as string
In the stackblitz I put the three cases
mat-selectreceive actually[]employees = this.employees ? this.employees.map(x=>x.EmployeeDto) : [];