将选择元素绑定到Angular中的对象


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。

但是,我实际上想绑定到country对象本身,所以它selectedValue是对象,而不仅仅是id。我试图像这样更改选项的值:

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

但这似乎不起作用。它似乎在我的对象中放置了一个对象,selectedValue但未在我期望的对象中放置。您可以在我的Plunker示例中看到这一点

我还尝试绑定到change事件,以便可以根据所选的id自己设置对象;但是,似乎更改事件在绑定的ngModel更新之前就触发了-这意味着我当时无法访问新选择的值。

有没有一种干净的方法可以将选择元素绑定到带有Angular 2的对象?


刚意识到我的Plunk在IE和Chrome中的工作方式有些不同。没有人真正按照我想要的方式工作,但仅供参考。
RHarris '16

Answers:


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

StackBlitz示例

注意:您可以使用[ngValue]="c"代替,[ngValue]="c.id"而c是完整的国家/地区对象。

[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
进行了尝试,但这似乎仅将数据从Dropdown绑定到模型。如果进入已经设置了模型的页面,则不会相应设置下拉菜单……
Strinder

13
@Strinder经常犯的错误是使用for selectedValue以外的其他对象实例c(默认项)。即使具有相同属性和值的其他对象也不起作用,它必须是相同的对象实例。
君特Zöchbauer

1
@GünterZöchbauer是的。已经想到了。因此,没有简单的方法可以直接与模型和值列表进行同步?=总是通过onChange吗?
Strinder

1
很快,我们便可以使用自定义比较器功能通过其属性比较ngModel对象。只需观看此问题:github.com/angular/angular/issues/13268
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]。这是不一样的。这对我
有用

2
角度4中的“#”错误
海千克

2
使用let而不是#@ sea-kg
Ashraful Islam

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中实现的方式。:)
路卡西·安德烈

帮助了我只有一个列表的地方,并且更改了一个值不应更新下一个列表,因此它有助于在不使用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]="compareByOptionIdselect

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

如果您还想处理change事件以做一些额外的事情(例如通知change回调),则很好。尽管在这种情况下,您只需要[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>

该方法总是可行的,但是,如果您有动态列表,请确保在模型之前加载它

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.