18

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!

NicuVlad
  • 2,491
  • 3
  • 28
  • 47
  • did you try adding [compareWith]="defineYourCompareFunction" to your mat-select ? – Ala Abid May 17 '19 at 13:50
  • @ala, no. I didn't knew about this property – NicuVlad May 17 '19 at 13:52
  • `compareFunction(o1: any, o2: any) { if(o1.name == o2.name && o1.id == o2.id ) return true; else return false }` – Ala Abid May 17 '19 at 13:52
  • that's an example compare function, try it and let me know – Ala Abid May 17 '19 at 13:53
  • From the documentation: /** A 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. **/ – NicuVlad May 17 '19 at 13:54
  • That's right, you define the criteria based on which an object become considered as selected. – Ala Abid May 17 '19 at 13:58

2 Answers2

27

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);
}
Ala Abid
  • 2,256
  • 23
  • 35
1

I agree with above answer I am posting this for users who have Angular mat-select and using reactive forms.

You can use the patchValue of Angular Reactive forms to have the default value selected

in your component in ngOnInit() or any place you want to have your dropdown selected value call patchValue function like below code:

  this.yourFrom.patchValue({
      CategoryID:1
    });
MJ X
  • 8,506
  • 12
  • 74
  • 99