Установленное значение <mat-select> программно

Я пытаюсь установить значение 2 полей <input matInput> abnd <mat-select> программно. Для ввода текста все работает как ожидалось, однако для <mat-select> в представлении это поле похоже на то, что значение будет иметь значение null. Но если я буду называть console.log(productForm.controls['category'].value он печатает правильное значение, которое я устанавливал программным console.log(productForm.controls['category'].value. Я что-то упустил?

Вот код:

form config:

productForm = new FormGroup({
        name: new FormControl('', [
            Validators.required
        ]),
        category: new FormControl('', [
            Validators.required
        ]),
    });

значение настройки:

ngOnInit() {
        this.productForm.controls['name'].setValue(this.product.name);
        this.productForm.controls['category'].setValue(this.product.category);
    }
}

HTML:

<mat-form-field>
<mat-select [formControlName]="'category'"
            [errorStateMatcher]="errorStateMatcher">
    <mat-option *ngFor="let category of categories" [value]="category">
        {{category.name}}
    </mat-option>
</mat-select>

Ответ 1

Решена проблема с изменением значения <mat-option> от объекта category до его идентификатора.

<mat-form-field>
<mat-select [formControlName]="'category'"
        [errorStateMatcher]="errorStateMatcher">
<mat-option *ngFor="let category of categories" [value]="category.id">
    {{category.name}}
</mat-option>
</mat-select>
</mat-form-field>

и значение настройки:

this.productForm.controls['category'].setValue(this.product.category.id);

Ответ 2

Angular mat-select сравнивает по ссылке между этим объектом и всеми доступными объектами в mat-select. В результате он не может выбрать элементы, которые вы установили в поле категории. Следовательно, вам необходимо реализовать функцию сравнения, чтобы сравнить любые атрибуты элемента списка, как вы хотите, а затем передать эту функцию в атрибут [compareWith] mat-select.
В заключение вот снимок для окончательной разметки и сценария:

<mat-form-field>
<mat-select [formControlName]="category" [compareWith]="compareCategoryObjects">
    <mat-option *ngFor="let category of categories" [value]="category">
        {{category.name}}
    </mat-option>
</mat-select>

И в классе компонентов:

compareCategoryObjects(object1: any, object2: any) {
        return object1 && object2 && object1.id == object2.id;
    }

Теперь он будет выбирать элементы -or, если для поля установлено несколько select-.

Справка:
https://github.com/angular/material2/issues/10214

Рабочий образец:
https://stackblitz.com/edit/angular-material2-issue-t8rp7j

Ответ 3

То, как вы можете достичь этого с помощью объектов, - это изменить разметку следующим образом:

<mat-select [formControlName]="'category'"
        [errorStateMatcher]="errorStateMatcher" [compareWith]="compareFn">
<mat-option *ngFor="let category of categories" [value]="category">
    {{category.name}}
</mat-option>
</mat-select>

Тогда в компоненте

compareFn(x: Category, y: Category): boolean {
return x && y ? x.id === y.id : x === y;
}

Ответ 4

Я думаю, что здесь вы должны использовать FormGroup.setValue.

Согласно вашему коду,

this.productForm.setValue({
name: this.product.name,
category: this.product.category
});

Для получения дополнительной информации, пожалуйста, обратитесь к документации