Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2/4 mat-select multiple ngModel

I have a mat-select dropdownlist with multiple enabled and am using NgModel to store user selected values.

Problem is when I navigate to another page and come back the user-selected values aren't in the mat-select..I know the ngModel has those values...I am missing something...

HTML

<mat-form-field>
 <mat-select placeholder="Customers" name="customerDetails" ngDefaultControl       
 formControlName="customerDetails" [(ngModel)]="custonerDetails" 
 [formControl]="customerDetailsCtrl" multiple   
 (ngModelChange)="onCustomerValueChanges(customer)" >
 
  <mat-option *ngFor="let customer of customerDetailsResult"
  [value]="customer">{{customer.CustomerNo}}- 
                     {{customer.CustomerDescription}}
   </mat-option>
 </mat-select>
</mat-form-field>

Any ideas?

like image 901
Ram Avatar asked Oct 10 '17 09:10

Ram


1 Answers

Depending on a use-case initializing some default options as selected might not work by simply binding to the ngModel, because objects in the options and in the selected subset from the previous state have different identities. Thanks to the support for compareWith it is possible to set them as selected.

Have a look at the offical Angular docs here.

In Material2 demo-app they have an example of the function with two implementations. It's here.

In my component I have a collection of User objects [people] for the options of mat select. The component receives a collection of selected User objects [users] as Input from previous state. Fair enough, objects in [people] and objects in [users] have different identities and the subset in the multiple select does not initialize with selected checkboxes by default.

So, the magical compareWith just literally compares objects by some given values and returns true or false, and the checkboxes on the subset of [people] get the status of selected. In my code I decided to go with [(ngModel]) binding:

<mat-form-field>
    <mat-select [compareWith]="compareFn" name="users" [(ngModel)]="users" multiple>
        <mat-option *ngFor="let person of people" [value]="person">
           {{ person.username }}
        </mat-option>
   </mat-select>
</mat-form-field>

And in the .ts file I utilize the function from the Angular doc to return true if two User objects have the same id:

compareFn(user1: User, user2: User) {
    return user1 && user2 ? user1.id === user2.id : user1 === user2;
}

If you have a similar use-case, it might work out-of-the-box.

On the what's-under-the-hood note, compareWith made me curious. I found out that it is based on a function in Angular2 called looseIdentical (have a look here), which in turn derives from the identical in Dart.js library by Google. It can be found here.

like image 92
RedDree Avatar answered Nov 04 '22 04:11

RedDree