Seçili öğeyi Açısal'da nesneye bağlama


409

Bir seçim öğesini bir nesne listesine bağlamak istiyorum - ki bu yeterince kolay:

@Component({
   selector: 'myApp',
   template: `<h1>My Application</h1>
              <select [(ngModel)]="selectedValue">
                 <option *ngFor="#c of countries" value="c.id">{{c.name}}</option>
              </select>`
})
export class AppComponent{
    countries = [
       {id: 1, name: "United States"},
       {id: 2, name: "Australia"}
       {id: 3, name: "Canada"},
       {id: 4, name: "Brazil"},
       {id: 5, name: "England"}
     ];
    selectedValue = null;
}

Bu durumda, selectedValuebir sayı gibi görünüyor - seçilen öğenin kimliği.

Ancak, aslında ülke nesnesinin kendisine bağlanmak istiyorum, bu yüzden selectedValuesadece id'den ziyade nesne budur. Ben böyle seçeneğin değerini değiştirmeyi denedim:

<option *ngFor="#c of countries" value="c">{{c.name}}</option>

ama bu işe yaramıyor gibi görünüyor. Görünüşe göre bir nesne koyuyorum selectedValue- ama beklediğim nesneyi değil. Bunu Plunker örneğimde görebilirsiniz .

Ben de seçilen kimliğe göre nesneyi kendim ayarlayabilmeniz için change olayına bağlanmayı denedim; Ancak, değişiklik olayı ilişkili ngModel güncellenmeden önce tetiklenir gibi görünüyor - yani o noktada yeni seçilen değere erişimim yok.

Seçili öğeyi Açısal 2 ile bir nesneye bağlamanın temiz bir yolu var mı?


Plunk'umun IE ve Chrome'da biraz farklı çalıştığını fark ettim. Aslında hiçbiri istediğim gibi çalışmıyor, ama FYI.
RHarris

Yanıtlar:


734
<h1>My Application</h1>
<select [(ngModel)]="selectedValue">
  <option *ngFor="let c of countries" [ngValue]="c">{{c.name}}</option>
</select>

StackBlitz örneği

NOT: c'nin tam ülke nesnesi olduğu yerde kullanmak [ngValue]="c"yerine kullanabilirsiniz [ngValue]="c.id".

[value]="..."sadece dize değerlerini
[ngValue]="..."destekler herhangi bir türü destekler

Güncelleme

Eğer valuebir amacı, önceden seçilmiş örneği değerinden biriyle aynı olması gerekmektedir.

Ayrıca, 4.0.0-beta.7'den beri mevcut olan yeni eklenen karşılaştırmaya https://github.com/angular/angular/issues/13268 bakın.

<select [compareWith]="compareFn" ...

Erişmek istediğiniz takdirde özen thisiçinde compareFn.

compareFn = this._compareFn.bind(this);

// or 
// compareFn = (a, b) => this._compareFn(a, b);

_compareFn(a, b) {
   // Handle compare logic (eg check if unique ids are the same)
   return a.id === b.id;
}

21
Denedim ama bu sadece Dropdown'dan modele veri bağlıyor gibi görünüyor. Model önceden ayarlanmış olan sayfaya
girilirse

13
@Strinder sık ​​görülen bir hata, selectedValuefor c(varsayılan öğe) yerine başka bir nesne örneği kullanmaktır . Aynı özelliklere ve değerlere sahip farklı bir nesne çalışmaz, aynı nesne örneği olmalıdır.
Günter Zöchbauer

1
@ GünterZöchbauer Evet. Zaten düşünce düşündüm. Yani doğrudan model ve bir değer listesi ile senkronize etmenin kolay bir yolu yok mu? = her zaman onChange aracılığıyla?
Strinder

1
Yakında ngModel nesnelerini özel karşılaştırıcı işlevini kullanarak özelliklerine göre karşılaştırabiliriz. Şu sorunu izleyin: github.com/angular/angular/issues/13268
kub1x

1
Bildiğinizde her zaman kolaydır ;-) ama angular.io/api/forms/NgSelectOption#description iyi dokümanlar içeren angular.io/api/forms/SelectControlValueAccessor bağlantısını içerir .
Günter Zöchbauer

41

Bu yardımcı olabilir:

    <select [(ngModel)]="selectedValue">
          <option *ngFor="#c of countries" [value]="c.id">{{c.name}}</option>
    </select>

5
[NgValue] yerine [değer] kullandım. Aynı şey değil. Bu benim için çalıştı
Carolina Faedo

2
Açısal 4'te '#' hatası
sea-kg

2
@ Sea-kg letyerine kullanın#
Ashraful Islam

1
Bu cevap seçilen değeri alamıyor
San Jaisy

20

Sen de kullanmaya gerek kalmadan yapabilirsiniz [(ngModel)]senin içinde <select>etiketi

Ts dosyanızda bir değişken bildirin

toStr = JSON.stringify;

ve şablonunuzda bunu yapın

 <option *ngFor="let v of values;" [value]="toStr(v)">
      {{v}}
 </option>

ve sonra kullan

let value=JSON.parse(event.target.value)

dizesini geçerli bir JavaScript nesnesine geri ayrıştırmak için


1
Bu gerçekten yapılabilir, ancak büyük nesnelerde ağrı olur. Ayrıca, Angular'ın değişiklik algılama alt çizgisi de düşünülmesi gereken bir şeydir. Bilgileri botlar tarafından kolayca ayrıştırılabilen json olarak çıkarmak, performans çekicilerine katkıda bulunur. Angular'ın değişiklik algılamasını kullanmak, verilerin mantığını gizler (kapsüller) ve size gerekli bilgileri sağlar. @ Günter Zöchbauer cevabı Angular'da bunu yapmanın yolu. :)
Lucaci Andrei

Tek bir liste vardı ve bir değeri değiştirmek sonraki güncelleme olmamalıdır bana yardımcı oldu, bu yüzden ngmodel kullanmadan bir kesmek olarak kullanarak yardımcı oldu, Teşekkürler :)
Melvin

Bu, düz JavaScript nesneleri için geçerlidir, ancak bir sınıfın örneklerindeki tüm yöntemleri kaybedeceğinizi unutmayın.
KhalilRavanna

13

Benim için çalıştı:

Şablon HTML'si:

Ben eklendi (ngModelChange)="selectChange($event)"kardeşime karşı select.

<div>
  <label for="myListOptions">My List Options</label>
  <select (ngModelChange)="selectChange($event)" [(ngModel)]=model.myListOptions.id >
    <option *ngFor="let oneOption of listOptions" [ngValue]="oneOption.id">{{oneOption.name}}</option>
  </select>
</div>

Component.ts sitesinde:

  listOptions = [
    { id: 0, name: "Perfect" },
    { id: 1, name: "Low" },
    { id: 2, name: "Minor" },
    { id: 3, name: "High" },
  ];

component.tsBu işleve eklemeniz gerekir :

  selectChange( $event) {
    //In my case $event come with a id value
    this.model.myListOptions = this.listOptions[$event];
  }

Not: Deniyorum [select]="oneOption.id==model.myListOptions.id"ve çalışmıyor.

============= Başka yollar olabilir: =========

Şablon HTML'si:

Ben eklendi [compareWith]="compareByOptionIdkardeşime karşı select.

<div>
  <label for="myListOptions">My List Options</label>
  <select [(ngModel)]=model.myListOptions [compareWith]="compareByOptionId">
    <option *ngFor="let oneOption of listOptions" [ngValue]="oneOption">{{oneOption.name}}</option>
  </select>
</div>

Component.ts sitesinde:

  listOptions = [
    { id: 0, name: "Perfect" },
    { id: 1, name: "Low" },
    { id: 2, name: "Minor" },
    { id: 3, name: "High" },
  ];

component.tsBu işleve eklemeniz gerekir :

 /* Return true or false if it is the selected */
 compareByOptionId(idFist, idSecond) {
    return idFist && idSecond && idFist.id == idSecond.id;
 }

Bu, fazladan bir şey yapmak için değişiklik olayını da işlemek istiyorsanız iyidir (değişiklik geri çağrısını bildirmek gibi). Bu durumda, yalnızca [ngModel]modelinizi tanımlanmış olan özel değişiklik geri aramanıza manuel olarak koymanız ve ayarlamanız gerekir (ngModelChange).
ezmek

9

Birisinin Reaktif Formları kullanarak aynı şeyi yapmak istemesi durumunda:

<form [formGroup]="form">
  <select formControlName="country">
    <option *ngFor="let country of countries" [ngValue]="country">{{country.name}}</option>
  </select>
  <p>Selected Country: {{country?.name}}</p>
</form>

Çalışma örneğini buradan kontrol edin


5

Bir İşlev Kullanarak Kimliği Seçebilirsiniz

<option *ngFor="#c of countries" (change)="onchange(c.id)">{{c.name}}</option>

4

Benim için böyle çalışıyor, konsollaşabilirsiniz event.target.value.

<select (change) = "ChangeValue($event)" (ngModel)="opt">   
    <option *ngFor=" let opt of titleArr" [value]="opt"></option>
</select>

2

Ayrıca, verilen çözümlerden başka bir şey işe yaramazsa, "AppModule" içine "FormsModule" aktarıp aktarmadığınızı kontrol edin, bu benim için bir anahtardı.


2

Seçili öğe için başka bir alıcı oluştur

<form [formGroup]="countryForm">
  <select formControlName="country">
    <option *ngFor="let c of countries" [value]="c.id">{{c.name}}</option>
  </select>

  <p>Selected Country: {{selectedCountry?.name}}</p>
</form>

Ts olarak:

get selectedCountry(){
  let countryId = this.countryForm.controls.country.value;
  let selected = this.countries.find(c=> c.id == countryId);
  return selected;
}

1

Seçilen değeri fonksiyonun içinden geçirerek click () yardımıyla da seçilen değeri alabilirsiniz.

<md-select placeholder="Select Categorie"  
    name="Select Categorie" >
  <md-option *ngFor="let list of categ" [value]="list.value" (click)="sub_cat(list.category_id)" >
    {{ list.category }}
  </md-option>
</md-select>

0

bu şekilde de kullanın ..

<h1>My Application</h1>
<select [(ngModel)]="selectedValue">
     <option *ngFor="let c of countries" value="{{c.id}}">{{c.name}}</option>
 </select>

0

İçinde app.component.html:

 <select type="number" [(ngModel)]="selectedLevel">
          <option *ngFor="let level of levels" [ngValue]="level">{{level.name}}</option>
        </select>

Ve app.component.ts:

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  levelNum:number;
  levels:Array<Object> = [
      {num: 0, name: "AA"},
      {num: 1, name: "BB"}
  ];

  toNumber(){
    this.levelNum = +this.levelNum;
    console.log(this.levelNum);
  }

  selectedLevel = this.levels[0];

  selectedLevelCustomCompare = {num: 1, name: "BB"}

  compareFn(a, b) {
    console.log(a, b, a && b && a.num == b.num);
    return a && b && a.num == b.num;
  }
}

0

<select name="typeFather"
    [(ngModel)]="type.typeFather">
        <option *ngFor="let type of types" [ngValue]="type">{{type.title}}</option>
</select>

Bu yaklaşım her zaman işe yarayacaktır, ancak dinamik bir listeniz varsa , modelden önce yüklediğinizden emin olun

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.