typescript - Angular Material: mat-select väljer inte standard
Jag har en mat-select där alternativen är alla objekt definierade i en array. Jag försöker ställa in värdet som standard till ett av alternativen, men det lämnas kvar valt när sidan renderas.
Min maskinskrivna fil innehåller:
public options2 = [
{"id": 1, "name": "a"},
{"id": 2, "name": "b"}
]
public selected2 = this.options2[1].id;
Min HTML-fil innehåller:
<div>
<mat-select
[(value)]="selected2">
<mat-option
*ngFor="let option of options2"
value="{{ option.id }}">
{{ option.name }}
</mat-option>
</mat-select>
</div>
Jag har försökt sätta selected2 och value i mat-option till både objektet och dess id, och har försökt använda både [(value)] och [(ngModel)] i mat-select, men ingen fungerar.
Jag använder material version 2.0.0-beta.10
Svar #1
Använd en bindning för värdet i din mall.
value="{{ option.id }}"
borde vara
[value]="option.id"
Och i ditt valda värde, använd ngModel istället för value.
<mat-select [(value)]="selected2">
borde vara
<mat-select [(ngModel)]="selected2">
Komplett kod:
<div>
<mat-select [(ngModel)]="selected2">
<mat-option *ngFor="let option of options2" [value]="option.id">{{ option.name }}</mat-option>
</mat-select>
</div>
Som en bisats, från och med version 2.0.0-beta.12 accepterar materialselect nu ett mat-form-field-element som föräldraelement så att det är konsekvent med de andra materialinmatningskontrollerna. Byt ut div-elementet mot mat-form-field-elementet efter att du uppgraderat.
<mat-form-field>
<mat-select [(ngModel)]="selected2">
<mat-option *ngFor="let option of options2" [value]="option.id">{{ option.name }}</mat-option>
</mat-select>
</mat-form-field>
Svar #2
Använd compareWith, en funktion för att jämföra alternativvärdena med de valda värdena. se här: https://material.angular.io/components/select/api#MatSelect
För ett objekt med följande struktur:
listOfObjs = [{ name: 'john', id: '1'}, { name: 'jimmy', id: '2'},...]
Definiera markup så här:
<mat-form-field>
<mat-select
[compareWith]="compareObjects"
[(ngModel)]="obj">
<mat-option *ngFor="let obj of listOfObjs" [value]="obj">
{{ obj.name }}
</mat-option>
</mat-select>
</mat-form-field>
Och definiera jämförelsefunktionen så här:
compareObjects(o1: any, o2: any): boolean {
return o1.name === o2.name && o1.id === o2.id;
}
Svar #3
Jag använder Angular 5 och reaktiva formulär med mat-select och kunde inte få någon av ovanstående lösningar att visa det initiala värdet.
Jag var tvungen att lägga till [compareWith] för att hantera de olika typer som används inom mat-select-komponenten. Internt verkar det som att mat-select använder en array för att hålla det valda värdet. Detta är sannolikt för att möjliggöra att samma kod fungerar med flera val om det läget är aktiverat.
Angular Välj Kontroll Dokumentation
Här är min lösning:
Formulärbyggare för att initiera formulärkontrollen:
this.formGroup = this.fb.group({
country: new FormControl([ this.myRecord.country.id ] ),
...
});
Implementera sedan compareWith-funktionen på din komponent:
compareIds(id1: any, id2: any): boolean {
const a1 = determineId(id1);
const a2 = determineId(id2);
return a1 === a2;
}
Nästa steg är att skapa och exportera determineId-funktionen (jag var tvungen att skapa en fristående funktion så att mat-select kunde använda den):
export function determineId(id: any): string {
if (id.constructor.name === 'array' && id.length > 0) {
return '' + id[0];
}
return '' + id;
}
Lägg slutligen till compareWith-attributet till din mat-select:
<mat-form-field hintLabel="select one">
<mat-select placeholder="Country" formControlName="country"
[compareWith]="compareIds">
<mat-option>None</mat-option>
<mat-option *ngFor="let country of countries" [value]="country.id">
{{ country.name }}
</mat-option>
</mat-select>
</mat-form-field>
Svar #4
Du bör binda det som [value] i mat-option enligt nedan,
<mat-select placeholder="Panel color" [(value)]="selected2">
<mat-option *ngFor="let option of options2" [value]="option.id">
{{ option.name }}
</mat-option>
</mat-select>
LIVE DEMO
Svar #5
Du kan enkelt implementera din egen jämförelsefunktion
[compareWith]="compareItems"Se även dokumentationen. Så den kompletta koden skulle se ut så här:
<div>
<mat-select
[(value)]="selected2" [compareWith]="compareItems">
<mat-option
*ngFor="let option of options2"
value="{{ option.id }}">
{{ option.name }}
</mat-option>
</mat-select>
</div>
och i Typescript-filen:
compareItems(i1, i2) {
return i1 && i2 && i1.id===i2.id;
}
