Angular Material: mat-select default value when using reactive forms

NicuVlad picture NicuVlad · May 17, 2019 · Viewed 7.4k times · Source

I created a form using reactive forms and angular material mat-select which I use to create an object called "core". The core object has 2 properties: "name" and "owners". The "owners" property is an array of IUser objects.

The core object:

export interface ICore {
  id?: number;
  name: string;
  owners: IUser[];
}

The form:

<form [formGroup]="parentForm">
      <mat-form-field class="example-full-width">
        <input matInput formControlName="name" placeholder="Name">
      </mat-form-field>

      <mat-form-field class="example-full-width">
        <mat-label>Users</mat-label>
        <mat-select formControlName="owners" multiple>
          <mat-option *ngFor="let user of users" [value]="user"> {{ user.username }}</mat-option>
        </mat-select>
      </mat-form-field>
    </form>

The "users" variable is an array of all available users that can be selected.

 users: IUser[];

The form works great but now I want to use the same form to edit a core object and for that I need to display the core owners in the "owners" form control when the page is loaded.

Form creation:

  createForm() {
    this.coreForm = this.formBuilder.group({
      name: ['', [Validators.required]],
      owners: ['', [Validators.required]]
    });
  }

How I get the core:

getCore() {
    this.coreService.getCore(this.route.snapshot.params['id'])
      .subscribe(
        res => {
          this.core = res;
          this.updateForm();
        },
        err => this.toastr.error('Core has not been received!', 'Error!')
      );
  }

Form update(it works for the name property):

  updateForm() {
        this.coreForm.patchValue({
          name: this.core.name,
          owners: this.core.owners
        });
      }

But the owners list is not added. The strange thing is that if I update the form with the users it works:

  getUsers() {
    this.usersService.getUsers()
    .subscribe(
      res => {
        this.users = res;
        this.coreForm.patchValue({
          owners: res
        });
      },
      err => this.toastr.error('User could not be received!', 'Error!')
    );
  }

This way all the users are added as the default value. But for the core owners it's not working. Any idea what I do wrong here?

Thanks in advance!

Answer

Ala Abid picture Ala Abid · May 17, 2019

You need to define the criteria based on which an object becomes considered as selected using the [compareWith] directive as follows:

<form [formGroup]="parentForm">
      <mat-form-field class="example-full-width">
        <input matInput formControlName="name" placeholder="Name">
      </mat-form-field>

      <mat-form-field class="example-full-width">
        <mat-label>Users</mat-label>
        <mat-select [compareWith]="compareFunction" formControlName="owners" multiple>
          <mat-option *ngFor="let user of users" [value]="user"> {{ user.username }}</mat-option>
        </mat-select>
      </mat-form-field>
</form>

and define your compareFunction:

compareFunction(o1: any, o2: any) {
 return (o1.name == o2.name && o1.id == o2.id);
}