wake-up-neo.com

Angular Material: Mattenauswahl wählt Standard nicht aus

Ich habe ein Auswahlfeld, bei dem die Optionen alle in einem Array definierten Objekte sind. Ich versuche, den Wert auf eine der Optionen als Standard festzulegen, er wird jedoch beim Rendern der Seite ausgewählt.

Meine TypeScript-Datei enthält:

  public options2 = [
    {"id": 1, "name": "a"},
    {"id": 2, "name": "b"}
  ]
  public selected2 = this.options2[1].id;

Meine HTML-Datei enthält:

  <div>
    <mat-select
        [(value)]="selected2">
      <mat-option
          *ngFor="let option of options2"
          value="{{ option.id }}">
        {{ option.name }}
      </mat-option>
    </mat-select>
  </div>

Ich habe versucht, selected2 und die value in mat-option für sowohl das Objekt als auch dessen ID einzustellen, und habe versucht, sowohl [(value)] als auch [(ngModel)] in mat-select zu verwenden, aber es funktioniert nicht.

Ich verwende Materialversion 2.0.0-beta.10

Vielen Dank

51
William Moore

Verwenden Sie eine Bindung für den Wert in Ihrer Vorlage.

value="{{ option.id }}"

sollte sein 

[value]="option.id"

Verwenden Sie in Ihrem ausgewählten Wert ngModel anstelle von value.

<mat-select [(value)]="selected2">

sollte sein 

<mat-select [(ngModel)]="selected2">

Vollständiger Code:

<div>
  <mat-select [(ngModel)]="selected2">
    <mat-option *ngFor="let option of options2" [value]="option.id">{{ option.name }}</mat-option>
  </mat-select>
</div>

Seit Version 2.0.0-beta.12 das material select akzeptiert jetzt ein mat-form-field-Element als übergeordnetes Element, sodass es mit den anderen Materialeingabesteuerelementen konsistent ist. Ersetzen Sie nach dem Upgrade das Element div durch das Element mat-form-field.

<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>
61
Igor

Verwenden Sie compareWith, eine Funktion, um die Optionswerte mit den ausgewählten Werten zu vergleichen. siehe hier: https://material.angular.io/components/select/api#MatSelect

Für ein Objekt der folgenden Struktur:

listOfObjs = [{ name: 'john', id: '1'}, { name: 'jimmy', id: '2'},...]

Definieren Sie das Markup folgendermaßen: 

<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>

Und definieren Sie die Vergleichsfunktion wie folgt: 

compareObjects(o1: any, o2: any): boolean {
  return o1.name === o2.name && o1.id === o2.id;
}
35
Badis Merabet

Ich verwende Angular 5 und reaktive Formulare mit mat-select und konnte keine der oben genannten Lösungen zur Anzeige des Anfangswerts verwenden. 

Ich musste [compareWith] hinzufügen, um mich mit den verschiedenen Typen zu beschäftigen, die in der mat-select-Komponente verwendet werden. Es scheint, als würde mat-select ein Array verwenden, um den ausgewählten Wert zu speichern. Dies lässt wahrscheinlich zu, dass derselbe Code mit mehreren Auswahlen funktioniert, wenn dieser Modus aktiviert ist.

Angular Select Control Doc

Hier ist meine Lösung:

Form Builder zum Initialisieren der Formularsteuerung:

this.formGroup = this.fb.group({
    country: new FormControl([ this.myRecord.country.id ] ),
    ...
});

Implementieren Sie anschließend die Funktion compareWith in Ihrer Komponente:

compareIds(id1: any, id2: any): boolean {
    const a1 = determineId(id1);
    const a2 = determineId(id2);
    return a1 === a2;
}

Erstellen und exportieren Sie als Nächstes die determinierte Funktion (ich musste eine eigenständige Funktion erstellen, damit mat-select sie verwenden kann): 

export function determineId(id: any): string {
    if (id.constructor.name === 'array' && id.length > 0) {
       return '' + id[0];
    }
    return '' + id;
}

Fügen Sie schließlich das compareWith-Attribut zu Ihrem mat-select hinzu:

<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>
12
Heather92065

Sie sollten es als [value] im mat-option wie folgt binden.

<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

10
Aravind

Meine Lösung ist etwas kniffeliger und einfacher. 

<div>
    <mat-select
        [placeholder]="selected2">
      <mat-option
          *ngFor="let option of options2"
          value="{{ option.id }}">
        {{ option.name }}
      </mat-option>
    </mat-select>
  </div>

Ich habe gerade den Platzhalter verwendet. Die Standardfarbe des Materialplatzhalters ist light gray. Damit es so aussieht, als wäre die Option ausgewählt, habe ich das CSS wie folgt manipuliert:

::ng-deep .mat-select-placeholder {
    color: black;
}
3

Wie bereits in Angular 6 erwähnt, wird die Verwendung von ngModel in reaktiven Formen nicht mehr empfohlen (und in Angular 7 entfernt). Daher habe ich die Vorlage und die Komponente wie folgt geändert.

Die Vorlage:

<mat-form-field>
    <mat-select [formControl]="filter" multiple 
                [compareWith]="compareFn">
        <mat-option *ngFor="let v of values" [value]="v">{{v.label}}</mat-option>
    </mat-select>
</mat-form-field>

Die Hauptkomponenten der Komponente (onChanges und andere Details werden weggelassen):

interface SelectItem {
    label: string;
    value: any;
}

export class FilterComponent implements OnInit {
    filter = new FormControl();

    @Input
    selected: SelectItem[] = [];

    @Input()
    values: SelectItem[] = [];

    constructor() { }

    ngOnInit() {
        this.filter.setValue(this.selected);
    }

    compareFn(v1: SelectItem, v2: SelectItem): boolean {
        return compareFn(v1, v2);
    }
}

function compareFn(v1: SelectItem, v2: SelectItem): boolean {
    return v1 && v2 ? v1.value === v2.value : v1 === v2;
}

Beachten Sie this.filter.setValue (this.selected) in ngOnInit oben.

Es scheint in Angular 6 zu funktionieren.

3
mp31415

Die Lösung für mich war:

<mat-form-field>
  <mat-select #monedaSelect  formControlName="monedaDebito" [attr.disabled]="isLoading" [placeholder]="monedaLabel | async ">
  <mat-option *ngFor="let moneda of monedasList" [value]="moneda.id">{{moneda.detalle}}</mat-option>
</mat-select>

TS:

@ViewChild('monedaSelect') public monedaSelect: MatSelect;
this.genericService.getOpciones().subscribe(res => {

  this.monedasList = res;
  this.monedaSelect._onChange(res[0].id);


});

Objekt verwenden: {id: number, detalle: string}

1
Seba Arce

Versuche dies!

this.selectedObjectList = [{id:1}, {id:2}, {id:3}]
this.allObjectList = [{id:1}, {id:2}, {id:3}, {id:4}, {id:5}]
let newList = this.allObjectList.filter(e => this.selectedObjectList.find(a => e.id == a.id))
this.selectedObjectList = newList
1
Facu Quintana

Ich habe es genauso gemacht wie in diesen Beispielen. Es wurde versucht, den Wert der Mat-Select auf den Wert einer der Mat-Optionen zu setzen. Aber scheiterte. 

Mein Fehler war es, [(value)] = "someNumberVariable" mit einer numerischen Typvariablen zu tun, während die in mat-options Strings waren. Selbst wenn sie in der Vorlage gleich aussehen würden, würde sie diese Option nicht auswählen. 

Nachdem ich die someNumberVariable zu einer Zeichenfolge geparst hatte, war alles in Ordnung. 

Es scheint also, dass Sie die mat-select-Werte und die mat-option-Werte nicht nur dieselbe Zahl haben müssen (wenn Sie Zahlen präsentieren), sondern auch den Typ string haben. 

1
jg80

Sie können einfach eine eigene Vergleichsfunktion implementieren

[compareWith]="compareItems"

Siehe auch docu . Der vollständige Code würde also so aussehen:

  <div>
    <mat-select
        [(value)]="selected2" [compareWith]="compareItems">
      <mat-option
          *ngFor="let option of options2"
          value="{{ option.id }}">
        {{ option.name }}
      </mat-option>
    </mat-select>
  </div>

und in der TypeScript-Datei:

  compareItems(i1, i2) {
    return i1 && i2 && i1.id===i2.id;
  }
0
LeO