Angularでselect要素をオブジェクトにバインドする


409

select要素をオブジェクトのリストにバインドしたいと思います-これは十分簡単です:

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

この場合、selectedValue数値、つまり選択したアイテムのIDであるように見えます。

ただし、実際には国オブジェクト自体にバインドしたいので、それselectedValueは単なるidではなくオブジェクトです。私はそのようにオプションの値を変更してみました:

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

しかし、これは機能していないようです。それは私の中にオブジェクトを配置するようですselectedValue-しかし、私が期待しているオブジェクトではありません。これは私のPlunkerの例で見ることができます

また、選択したIDに基づいて自分でオブジェクトを設定できるように、変更イベントにバインドしようとしました。ただし、バインドされたngModelが更新される前にchangeイベントが発生するようです。つまり、その時点で新しく選択された値にアクセスできません。

Angular 2でselect要素をオブジェクトにバインドするきれいな方法はありますか?


IEとChromeでPlunkの動作が少し異なることに気づきました。どちらも私が望んでいる方法で実際に機能するのではなく、参考までに。
RHarris 2016年

回答:


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

StackBlitzの例

注:cが完全な国オブジェクトの[ngValue]="c"代わりに使用でき[ngValue]="c.id"ます。

[value]="..."文字列値のみをサポート
[ngValue]="..."し、任意のタイプをサポートします

更新

場合valueオブジェクトである、予め選択されたインスタンスは、値のいずれかと同一である必要があります。

4.0.0-beta.7以降で利用可能な最近追加されたカスタム比較https://github.com/angular/angular/issues/13268 も参照してください。

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

this内でアクセスする場合は注意してください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
試してみましたが、これはドロップダウンからモデルにのみデータバインドするようです。モデルが既に設定されているページに入ると、ドロップダウンはそれに応じて設定されません...
Strinder

13
@Strinderのよくある間違いはselectedValue、for c(デフォルトのアイテム)以外のオブジェクトインスタンスを使用することです。同じプロパティと値を持つ別のオブジェクトは機能しません。同じオブジェクトインスタンスである必要があります。
ギュンターZöchbauer

1
@GünterZöchbauerええ。すでに考えた。モデルと値のリストを直接同期する簡単な方法はありませんか?=常にonChangeを介して?
Strinder、

1
間もなく、カスタムコンパレーター関数を使用して、ngModelオブジェクトをそのプロパティで比較できるようになるかもしれません。この問題をご覧ください
kub1x

1
知っていれば簡単です;-)ただし、angular.io / api / forms / NgSelectOption#descriptionには、優れたドキュメントを含むangular.io/api/forms/SelectControlValueAccessorリンクが含まれています。
ギュンターZöchbauer

41

これは役立ちます:

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

5
[ngValue]の代わりに[value]を使用しました。同じではありません。これは私にとってはうまくいった
カロライナ・フェード

2
角度4の「#」に関するエラー
sea-kg

2
@ sea-kgのlet代わりに使用する#
Ashraful Islam 2018

1
この答えは選択された値を取得しません
San Jaisy

20

タグで使用する必要なく、これも行うことができ[(ngModel)]ます<select>

tsファイルで変数を宣言する

toStr = JSON.stringify;

あなたのテンプレートでこれをしてください

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

次に使用します

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

文字列を解析して有効なJavaScriptオブジェクトに戻す


1
これは実際に実行可能ですが、大きなオブジェクトでは苦痛になります。また、Angularの下線の変更検出機能は、検討する必要があります。ボットが簡単に解析できるjsonとして情報を出力すると、パフォーマンスが向上します。Angularの変更検出を使用すると、データのロジックが非表示(カプセル化)され、必要な情報が確実に提供されます。@GünterZöchbauerの答えは、Angularでそれを行う方法です。:)
Lucaci Andrei

単一のリストがあり、1つの値を変更しても次のリストは更新されないので、ngmodelを使用せずにこれをハックとして使用できるようになりました。ありがとう:)
Melvin

これは単純なJavaScriptオブジェクトに対しては機能しますが、クラスのインスタンスについては、その上にあるすべてのメソッドを失うことに注意してください。
KhalilRavanna

13

それは私のために働きました:

テンプレートHTML:

に追加(ngModelChange)="selectChange($event)"しました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で:

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

component.tsこの関数に追加する必要があります:

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

注:私は [select]="oneOption.id==model.myListOptions.id"、動作しません。

=============別の方法は次のとおりです。=========

テンプレートHTML:

に追加[compareWith]="compareByOptionIdしました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で:

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

component.tsこの関数に追加する必要があります:

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

これは、変更イベントも処理して何か追加のことをしたい場合に便利です(変更コールバックに通知するなど)。その場合でも、で[ngModel]定義したカスタム変更コールバックにモデルを手動で配置して設定するだけで済みます(ngModelChange)
クラッシュ

9

誰かがリアクティブフォームを使用して同じことを実行しようとしている場合に備えて:

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

ここで実際の例を確認してください


5

関数を使用してIDを選択できます

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

4

私の場合、このように機能するので、コンソールできますevent.target.value

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

2

また、特定のソリューションで他に何も機能しない場合は、「AppModule」内に「FormsModule」をインポートしたかどうかを確認してください。これが私にとって重要でした。


2

選択したアイテムに別のゲッターを作成します

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

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

1

関数を介して選択した値を渡すことにより、click()の助けを借りて選択した値を取得することもできます

<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

この方法も使用します。

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

0

app.component.html

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

そして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>

このアプローチは常に機能しますが、動的リストがある場合は、モデルの前にロードしてください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.