Açısal Malzeme: mat-select varsayılanı seçmiyor


109

Seçeneklerin bir dizide tanımlanan tüm nesneler olduğu bir mat-select'im var. Değeri varsayılan olarak seçeneklerden birine ayarlamaya çalışıyorum, ancak sayfa oluşturulduğunda seçili olarak bırakılıyor.

Typescript dosyam şunları içerir:

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

HTML dosyam şunları içeriyor:

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

Hem nesneye hem de kimliğine ayarlamayı selected2ve valuegiriş mat-optionyapmayı denedim [(value)]ve hem hem de [(ngModel)]içinde kullanmayı denedim mat-select, ancak hiçbiri çalışmıyor.

Malzeme sürümü 2.0.0-beta.10 kullanıyorum


2
Kullanın compareWith. Daha zarif.
Badis Merabet

OLMALIDIR compareWith,
badis

Yanıtlar:


144

Şablonunuzdaki değer için bir bağlama kullanın.

value="{{ option.id }}"

olmalı

[value]="option.id"

Ve sizin seçtiğiniz değerde ngModelyerine kullanın value.

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

olmalı

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

Tam kod:

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

2.0.0-beta.12 sürümünden itibaren bir yan notta , malzeme seçimi artık bir mat-form-fieldöğeyi ana öğe olarak kabul eder , bu nedenle diğer malzeme girdi kontrolleriyle tutarlıdır. Yükseltme işleminden sonra divöğeyi elemanla değiştirin 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>

10
"Görünüşe göre ngModel'i formControlName ile aynı form alanında kullanıyorsunuz. NgModel input özelliğini ve ngModelChange olayını reaktif form direktifleriyle kullanma desteği, Angular v6'da kullanımdan kaldırıldı ve Angular v7'de kaldırılacak. Bununla ilgili daha fazla bilgi için burada bizim API docs bkz: angular.io/api/forms/FormControlName#use-with-ngmodel "
ldgorman

1
@ldgorman - Bu sonucu nasıl çıkardığınızı anlamıyorum. Eğer atıfta bulunuyorsanız mat-form-field, bu ..."used to wrap several Angular Material components and apply common Text field styles", yani aynı şey değil. OP ve ayrıca cevabım hiç bahsetmediler Bunun dışında FormControl, FormGroupya FormControlName.
Igor

1
Yukarıdaki ile aynı kodu uyguladıktan sonra bile aynı sorunu yaşıyorum @ Igor
Chuck

@Chuck - Hala sorun yaşıyorsanız lütfen yeni bir soru sorun ve tekrarlanabilir minimum bir örnek ekleyin . Göz atmamı isterseniz, bu yoruma bir bağlantıyla yanıt verebilirsiniz.
Igor

2
@ Igor- Biz bunu anladık, değer bir sayı olarak döndürülüyordu ve Mat-select onu bir dize arıyor. [compareWith]direktif kullandığımız şeydir
Chuck

94

compareWithSeçenek değerlerini seçilen değerlerle karşılaştırmak için, A işlevini kullanın . buraya bakın: https://material.angular.io/components/select/api#MatSelect

Aşağıdaki yapıdaki bir nesne için:

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

İşaretlemeyi şu şekilde tanımlayın:

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

Ve karşılaştırma işlevini şu şekilde tanımlayın:

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

8
Basit dizilerle değil, nesnelerle uğraşırken mükemmeldir. Teşekkür ederim.
Riaan van Zyl

25

Mat-select ile Angular 5 ve reaktif formları kullanıyorum ve başlangıç ​​değerini görüntülemek için yukarıdaki çözümlerden hiçbirini alamadım.

Mat-select bileşeninde kullanılan farklı türlerle başa çıkmak için [CompareWith] eklemem gerekti. Dahili olarak, mat-select'in seçilen değeri tutmak için bir dizi kullandığı görülmektedir. Bu, mod açıksa, muhtemelen aynı kodun birden fazla seçimle çalışmasına izin verir.

Açısal Seçimli Kontrol Belgesi

İşte benim çözümüm:

Form denetimini başlatmak için Form Oluşturucu:

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

Ardından, bileşeninize karşılaştırma işlevini uygulayın:

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

Daha sonra, determId işlevini oluşturun ve dışa aktarın (mat-select'in kullanabilmesi için bağımsız bir işlev oluşturmam gerekiyordu):

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

Son olarak, mat-select'inize CompareWith özelliğini ekleyin:

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

Çok teşekkürler! Sebep bulmak çok zordu.
Pax Beach

@ Heather92065 Bu benim için çalışan tek çözümdür. Sana minnettarım!
Latin Warrior

16

Sen olarak bağlayıcı olmalıdır [value]içinde mat-option, aşağıda

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

CANLI DEMO


Bu mükemmel çalışıyor. NgModel veya setValue () kullanımı başlatıldığında bu en kolay ve mükemmel yöntem
Rohit Parte

10

Kendi karşılaştırma işlevinizi kolayca uygulayabilirsiniz

[compareWith]="compareItems"

Belgeye de bakın . Yani kodun tamamı şöyle görünecektir:

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

ve Typescript dosyasında:

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

Bu benim için çalıştı ve bence bu çoğunlukla doğru yol ama liste sadece bir öğe içeriyorsa çalışmıyor. Teşekkürler
Kod Kadiya

Tek bir unsurla ne tür bir istisna elde edersiniz? Çünkü eğer var i1ya da i2olmayacaksa , karşılaştırma devreye girmeli .
LeO

6

Reaktif formlarda ngModel kullanarak Angular 6'da daha önce bahsedildiği gibi kullanımdan kaldırıldı (ve Angular 7'de kaldırıldı), bu yüzden şablonu ve bileşeni aşağıdaki gibi değiştirdim.

Şablon:

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

Bileşenin ana bölümleri ( onChangesve diğer ayrıntılar atlanmıştır):

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

Not this.filter.setValue (this.selected) içinde ngOnInit, yukarıda.

Angular 6'da çalışıyor gibi görünüyor.


Karşılaştırılacak iki farklı API sonucuyla uğraşırken aynı zamanda nesne seçimlerini de kapsadığından, bu aslında en iyi cevap olmalıdır.
Marco Klein

(örn. Seçilecek toplam öğe listesi ve başka bir api çağrısı içinde seçilen öğe).
Marco Klein

Angular 7 hala şablonlu modellerle çalışıyor! Ama aynı şablondaki reaktif formlarla karıştıramazsınız. [compareWith]
İle ilgili

3

Ben de aynen bu örneklerdeki gibi yaptım. Mat seçiminin değerini, mat seçeneklerinden birinin değerine ayarlamaya çalıştım. Ama başarısız oldu.

Benim hatam, mat-options içindekiler dizeler iken sayısal tip değişkene [(value)] = "someNumberVariable" yapmaktı. Şablonda aynı görünseler bile bu seçeneği seçmezdi.

SomeNumberVariable'ı bir dizeye ayrıştırdığımda her şey tamamen iyiydi.

Öyleyse, mat-select ve mat-option değerlerinin sadece aynı sayı (sayıları sunuyorsanız) olması değil, aynı zamanda onların string türünde olmasına da ihtiyacınız var gibi görünüyor.


Benim de sorunum buydu. Biri sayısaldı, diğeri bir dizeydi.
Vadim Berman

2

Benim için çözüm şuydu:

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


});

Nesneyi kullanma: {id: number, detalle: string}


1

Bunu dene!

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

Çözümüm biraz karmaşık ve daha basit.

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

Yer tutucuyu kullandım . Malzeme yer tutucusunun varsayılan rengi light gray. Seçeneğin seçilmiş gibi görünmesini sağlamak için CSS'yi şu şekilde değiştirdim:

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

1

Varsayılan değerin bağlanması veya ayarlanması, yalnızca MatSelect üzerindeki değer özniteliği, MatOption'a bağlanan değer özniteliğiyle karşılaştırılabilirse çalışır . Eğer bağlarsanız captioniçin öğenin değerini oznıtelığı mat-seçenek üzerinde varsayılan elemanı ayarlamalısınız elemanı mat-seçmek için captionçok öğenin. Eğer bağlarsanız Idiçin öğenin mat-seçeneğiyle , size bağlamak gerekir idiçin mat seçimini de bütün bir öğeyi, başlığını veya herhangi diğer yalnızca aynı alan.

Ama bunu bağlayıcı bir şekilde yapmanız gerekiyor []


1

Yukarıdakileri çok dikkatli takip ettim ve yine de ilk değeri seçemedim.

Bunun nedeni, bağlı değerimin typcript'te bir dize olarak tanımlanmış olmasına rağmen, arka uç API'mın bir sayı döndürmesiydi.

Javascript gevşek yazım, türü çalışma zamanında (hatasız) değiştirdi, bu da başlangıç ​​değerinin seçilmesini engelledi.

Bileşen

myBoundValue: string;

Şablon

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

Çözüm, bir dize değeri döndürmek için API'yi güncellemekti.


1

Bunu elde etmenin çok basit bir yolu formControl, FormGroupörneğin a (isteğe bağlı) içinde varsayılan bir değere sahip a kullanmaktır . Bu, bir alan girişine birim seçici kullanan bir örnektir:

ts

H_AREA_UNIT = 1;
M_AREA_UNIT = 2;

exampleForm: FormGroup;

this.exampleForm = this.formBuilder.group({
  areaUnit: [this.H_AREA_UNIT],
});

html

<form [formGroup]="exampleForm">
 <mat-form-field>
   <mat-label>Unit</mat-label>
   <mat-select formControlName="areaUnit">
     <mat-option [value]="H_AREA_UNIT">h</mat-option>
     <mat-option [value]="M_AREA_UNIT">m</mat-option>
   </mat-select>
 </mat-form-field>
</form>

0

Bir sayı ve dizge arasındaki bir karşılaştırma yanlıştır , bu nedenle, seçtiğiniz değeri ngOnInit içindeki bir dizeye çevirin ve işe yarayacaktır.

Aynı sorunu yaşadım, mat-select'i kullanarak bir enum ile doldurdum

Object.keys(MyAwesomeEnum).filter(k => !isNaN(Number(k)));

ve seçmek istediğim enum değerine sahiptim ...

Neden işe yaramadığını belirlemeye çalışırken birkaç saatimi zihnimle mücadele ederek geçirdim. Ve bunu mat-select'de kullanılan tüm değişkenleri, anahtar koleksiyonunu ve seçilenleri oluşturduktan hemen sonra yaptım ... ["0", "1", "2"] varsa ve 1'i seçmek istiyorsanız ( bu bir sayıdır) 1 == "1" yanlıştır ve bu nedenle hiçbir şey seçilmemiştir.

bu nedenle çözüm , seçtiğiniz değeri ngOnInit içindeki bir dizgeye çevirmektir ve işe yarayacaktır.


1
Merhaba Juan, JS'deki farklı eşitlik operatörleri hakkında ayrıntılara giren bu gönderiye bakmak isteyebilirsiniz: stackoverflow.com/questions/359494/…
William Moore

Merhaba William, bu harika bir gönderi, orada birkaç kez bulundum ... Ve nasıl karşılaştırılacağını öğrendim (umarım ve her zaman dokümanı gözden geçirebilirim) ... Buradaki sorun, malzeme denetleyicisi, farklı türlerin, sayıların ve dizelerin kullanıldığı yerde ... Bu denetleyici aynı türlere sahip olmayı bekler, bu nedenle, bir sayı seçilirse, koleksiyon bir sayılar koleksiyonu olmalıdır ... Sorun buydu.
Juan

0

Bunu ben yaptım.

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

[value]="option"Seçeneklerinizi bazı veritabanlarından almadığınız sürece normalde yapabilirsiniz ?? Bence ya veriyi almadaki gecikme çalışmamasına neden oluyor ya da alınan nesneler aynı olmasına rağmen bir şekilde farklı mı? Garip bir şekilde, büyük olasılıkla daha sonraki olanı, ben de denedim [value]="option === selected ? selected : option"ve işe yaramadı.


0

TS

   optionsFG: FormGroup;
   this.optionsFG = this.fb.group({
       optionValue: [null, Validators.required]
   });

   this.optionsFG.get('optionValue').setValue(option[0]); //option is the arrayName

HTML

   <div class="text-right" [formGroup]="optionsFG">
     <mat-form-field>
         <mat-select placeholder="Category" formControlName="optionValue">
           <mat-option *ngFor="let option of options;let i =index" [value]="option">
            {{option.Value}}
          </mat-option>
        </mat-select>
      </mat-form-field>
  </div>

0

public options2 = [
  {"id": 1, "name": "a"},
  {"id": 2, "name": "b"}
]
 
YourFormGroup = FormGroup; 
mode: 'create' | 'update' = 'create';

constructor(@Inject(MAT_DIALOG_DATA) private defaults: defautValuesCpnt,
      private fb: FormBuilder,
      private cd: ChangeDetectorRef) {
}
  
ngOnInit() {

  if (this.defaults) {
    this.mode = 'update';
  } else {
    this.defaults = {} as Cpnt;
  }

  this.YourFormGroup.patchValue({
    ...
    fCtrlName: this.options2.find(x => x.name === this.defaults.name).id,
    ... 
  });

  this.YourFormGroup = this.fb.group({
    fCtrlName: [ , Validators.required]
  });

}
  <div>
    <mat-select formControlName="fCtrlName"> <mat-option
          *ngFor="let option of options2"
          value="{{ option.id }}">
        {{ option.name }}
      </mat-option>
    </mat-select>
  </div>


Bu, güvenli bileşende Düzenle ve Güncelle'yi kullanırken yardımcı olacaktır
lilandos didas
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.