I’m using mat-select
in my Angular form to let users select multiple countries as objects with id
and name
properties. However, I need to patch the form control with the full country objects instead of just their IDs, but it doesn’t behave as expected. Here’s the relevant code snippet!!!
I need to patch the form control with full country objects instead of IDs, but currently, it's only working with country IDs.
<form [formGroup]="countryForm" (ngSubmit)="onSubmit()">
<mat-form-field appearance="outline">
<mat-label>Countries</mat-label>
<mat-select formControlName="countryControl" multiple >
<mat-option *ngFor="let country of countries" [value]="country">
{{ country.name }}
</mat-option>
</mat-select>
</mat-form-field>
</form>
<div>
<button mat-raised-button color="accent" type="button" (click)="patchFormWithCountry()">Patch Form</button>
</div>
Here is my ts:
import { Component } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
/** @title Form field appearance variants */
@Component({
selector: 'form-field-appearance-example',
templateUrl: 'form-field-appearance-example.html',
})
export class FormFieldAppearanceExample {
countryForm: FormGroup;
countries: any[] = [
{ id: 1, name: 'United States' },
{ id: 2, name: 'Canada' },
{ id: 3, name: 'United Kingdom' },
{ id: 4, name: 'Australia' },
{ id: 5, name: 'Germany' },
{ id: 6, name: 'France' },
{ id: 7, name: 'Italy' },
{ id: 8, name: 'Spain' },
{ id: 9, name: 'India' },
{ id: 10, name: 'China' },
{ id: 11, name: 'Japan' },
{ id: 12, name: 'Brazil' },
{ id: 13, name: 'South Africa' },
{ id: 14, name: 'Mexico' },
{ id: 15, name: 'Russia' },
];
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.countryForm = this.fb.group({
countryControl: [''],
});
}
patchFormWithCountry() {
const selectedCountries = [
{ id: 1, name: 'United States' },
{ id: 2, name: 'Canada' },
{ id: 3, name: 'United Kingdom' },
{ id: 4, name: 'Australia' },
];
this.countryForm.patchValue({
countryControl: selectedCountries,
});
}
onSubmit() {
console.log('Form submitted:', this.countryForm.value);
}
}
You need to implement the compareWith
function so that the <mat-select>
option can be mapped/patched when the value is a complex value such as an object.
Reference: Getting and setting the select value
<mat-select
formControlName="countryControl"
multiple
[compareWith]="countryCompareWithFn"
>
<mat-option *ngFor="let country of countries" [value]="country">
{{ country.name }}
</mat-option>
</mat-select>
countryCompareWithFn = (country: any, value: any) => country.id == value.id;