Liên kết chọn phần tử với đối tượng trong Angular


409

Tôi muốn liên kết một phần tử được chọn vào một danh sách các đối tượng - đủ dễ:

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

Trong trường hợp này, có vẻ như đó selectedValuesẽ là một số - id của mục được chọn.

Tuy nhiên, tôi thực sự muốn liên kết với chính đối tượng quốc gia để đó selectedValuelà đối tượng chứ không chỉ là id. Tôi đã cố gắng thay đổi giá trị của tùy chọn như vậy:

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

nhưng điều này dường như không hoạt động. Nó dường như đặt một đối tượng trong tôi selectedValue- nhưng không phải là đối tượng mà tôi mong đợi. Bạn có thể thấy điều này trong ví dụ Plunker của tôi .

Tôi cũng đã thử liên kết với sự kiện thay đổi để tôi có thể tự đặt đối tượng dựa trên id đã chọn; tuy nhiên, có vẻ như sự kiện thay đổi sẽ kích hoạt trước khi ngModel bị ràng buộc được cập nhật - có nghĩa là tôi không có quyền truy cập vào giá trị mới được chọn tại thời điểm đó.

Có cách nào rõ ràng để liên kết một phần tử được chọn với một đối tượng với Angular 2 không?


Chỉ cần nhận ra Plunk của tôi hoạt động hơi khác một chút trong IE so với Chrome. Không ai thực sự làm việc theo cách tôi muốn, nhưng FYI.
RHarris 11/03/2016

Câu trả lời:


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

Ví dụ về StackBlitz

LƯU Ý: bạn có thể sử dụng [ngValue]="c"thay vì [ngValue]="c.id"c là đối tượng quốc gia hoàn chỉnh.

[value]="..."chỉ hỗ trợ các giá trị chuỗi
[ngValue]="..."hỗ trợ bất kỳ loại nào

cập nhật

Nếu valuelà một đối tượng, thì đối tượng được chọn trước cần phải giống hệt với một trong các giá trị.

Xem thêm so sánh tùy chỉnh được thêm gần đây https://github.com/angular/angular/issues/13268 có sẵn kể từ 4.0.0-beta.7

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

Hãy cẩn thận nếu bạn muốn truy cập thistrong 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
Đã thử nó nhưng điều này dường như chỉ liên kết dữ liệu từ Dropdown đến mô hình. Nếu vào trang với mô hình đã được đặt, thả xuống sẽ không được đặt tương ứng ...
Strinder

13
@Strinder một lỗi thường xuyên là sử dụng một thể hiện đối tượng khác thay selectedValuevì cho c(mục mặc định). Một đối tượng khác ngay cả với cùng thuộc tính và giá trị không hoạt động, nó phải là cùng thể hiện đối tượng.
Günter Zöchbauer

1
@ GünterZöchbauer Vâng. Đã nghĩ đến ý nghĩ. Vì vậy, không có cách dễ dàng để đồng bộ trực tiếp với mô hình và danh sách các giá trị? = luôn luôn thông qua onChange?
Cuộc đình công

1
Chúng tôi có thể sớm so sánh các đối tượng ngModel bằng thuộc tính của chúng bằng chức năng so sánh tùy chỉnh. Chỉ cần xem vấn đề này: github.com/angular/angular/issues/13268
kub1x

1
Luôn luôn dễ dàng khi bạn biết điều đó ;-) nhưng angular.io/api/forms/NgSelectOption#description chứa một liên kết angular.io/api/forms/SelectControlValueAccessor với các tài liệu tốt.
Günter Zöchbauer

41

Điều này có thể giúp:

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

5
Tôi đã sử dụng [giá trị] thay vì [ngValue]. Nó không giống nhau. Điều này làm việc cho tôi
Carolina Faedo

2
Lỗi trên '#' ở góc 4
kg biển

2
Sử dụng letthay vì #@ sea-kg
Hồi giáo Ashraful

1
Câu trả lời này không nhận được giá trị được chọn
San Jaisy

20

Bạn cũng có thể làm điều này mà không cần sử dụng [(ngModel)]trong<select> thẻ

Khai báo một biến trong tệp ts của bạn

toStr = JSON.stringify;

và trong mẫu của bạn làm điều này

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

và sau đó sử dụng

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

để phân tích chuỗi trở lại thành một đối tượng JavaScript hợp lệ


1
Điều này thực sự là có thể làm được, nhưng trên các vật thể lớn sẽ trở thành một nỗi đau. Ngoài ra, khả năng phát hiện thay đổi của Angular là điều cần phải suy nghĩ. Xuất thông tin dưới dạng json, có thể dễ dàng phân tích cú pháp bởi bot, thêm vào hiệu suất. Sử dụng phát hiện thay đổi của Angular ẩn (đóng gói) logic của dữ liệu và đảm bảo cho bạn về thông tin cần thiết của bạn. @ Günter Zöchbauer trả lời là cách để làm điều đó trong Angular. :)
Lucaci Andrei

Đã giúp tôi nơi tôi có một danh sách duy nhất và thay đổi một giá trị không nên cập nhật tiếp theo vì vậy nó đã giúp sử dụng nó như một bản hack mà không sử dụng ngmodel, Cảm ơn :)
Melvin

Điều này hoạt động cho các đối tượng JavaScript đơn giản nhưng lưu ý cho các trường hợp của một lớp bạn sẽ mất tất cả các phương thức trên nó.
KhalilRavanna

13

Nó làm việc cho tôi:

Mẫu HTML:

Tôi đã thêm (ngModelChange)="selectChange($event)"vào của tôi 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>

Trên thành phần.ts:

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

Một bạn cần thêm vào component.tschức năng này:

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

Lưu ý: Tôi cố gắng với [select]="oneOption.id==model.myListOptions.id"và không làm việc.

============= Một cách khác có thể là: =========

Mẫu HTML:

Tôi đã thêm [compareWith]="compareByOptionIdvào của tôi 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>

Trên thành phần.ts:

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

Một bạn cần thêm vào component.tschức năng này:

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

Điều này là tốt nếu bạn cũng muốn xử lý sự kiện thay đổi để làm điều gì đó thêm (như thông báo một cuộc gọi lại thay đổi). Mặc dù trong trường hợp đó, bạn chỉ cần đặt [ngModel]và sau đó đặt mô hình của mình theo cách thủ công trong cuộc gọi lại thay đổi tùy chỉnh được xác định trong (ngModelChange).
nghiền nát

9

Chỉ trong trường hợp ai đó đang tìm cách làm điều tương tự bằng cách sử dụng Biểu mẫu phản ứng:

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

Kiểm tra ví dụ làm việc ở đây


5

Bạn có thể chọn Id bằng chức năng

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

4

Đối với tôi nó hoạt động như thế này, bạn có thể điều khiển event.target.value.

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

2

Ngoài ra, nếu không có gì khác từ các giải pháp đã cho không hoạt động, hãy kiểm tra xem bạn đã nhập "FormsModule" bên trong "AppModule" chưa, đó là một chìa khóa đối với tôi.


2

Tạo một getter khác cho mục đã chọn

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

Trong ts:

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

1

Bạn cũng có thể nhận giá trị được chọn với sự trợ giúp của nhấp () bằng cách chuyển giá trị đã chọn qua hàm

<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

sử dụng cách này cũng ..

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

0

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

Cách tiếp cận đó sẽ luôn hoạt động, tuy nhiên Nếu bạn có một danh sách động, hãy đảm bảo bạn tải nó trước mô hình

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.