Прив’язування елемента вибору до об'єкта в кутовому


409

Я хотів би прив’язати вибраний елемент до списку об’єктів - що досить просто:

@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було б число - ідентифікатор вибраного елемента.

Однак насправді я хотів би прив’язати до самого об'єкта країни так, що selectedValueце об'єкт, а не просто ідентифікатор. Я спробував змінити значення параметра так:

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

але це, здається, не працює. Здається, розміщувати об’єкт в моєму selectedValue- але не тому об’єкті, якого я очікував. Це ви можете побачити на моєму прикладі Plunker .

Я також спробував прив’язатись до події зміни, щоб я міг сам встановити об'єкт на основі вибраного ідентифікатора; однак, виявляється, що подія зміни запускається перед оновленням пов'язаного ngModel - це означає, що я не маю доступу до щойно вибраного значення в цій точці.

Чи є чистий спосіб прив’язати вибраний елемент до об'єкта з кутом 2?


Щойно зрозумів, що мій Plunk працює трохи по-іншому в IE і Chrome. Ні один насправді не працює так, як я хочу, але FYI.
RHarris

Відповіді:


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об'єктом є, попередньо вибраний екземпляр повинен бути ідентичним одному із значень.

Дивіться також нещодавно додане спеціальне порівняння https://github.com/angular/angular/isissue/13268, яке доступне з 4.0.0-beta.7

<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 до моделі. Якщо ви
входите

13
@Strinder частою помилкою є використання іншого екземпляра об'єкта, selectedValueніж для c(елемент за замовчуванням). Інший об'єкт навіть з однаковими властивостями та значеннями не працює, він повинен бути тим самим об'єктом.
Günter Zöchbauer

1
@ GünterZöchbauer Так. Вже думка думка. Тож немає простого способу синхронізації безпосередньо з моделлю та списком значень? = завжди через onChange?
Стрінджер

1
Незабаром ми зможемо порівняти об’єкти ngModel за їх властивістю за допомогою спеціальної функції порівняння. Просто дивіться це питання: github.com/angular/angular/isissue/13268
kub1x

1
Це завжди легко, коли ви це знаєте ;-), але angular.io/api/forms/NgSelectOption#description містить посилання angular.io/api/forms/SelectControlValueAccessor з хорошими документами.
Günter Zöchbauer

41

Це може допомогти:

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

5
Я використовував [value] замість [ngValue]. Це не те саме. Це працювало для мене
Кароліна Фаедо

2
Помилка на "#" у куті 4
морська кг

2
Використовуйте letзамість #@ морський кг
Ашрафульний іслам

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ünter Zöchbauer відповідь - це спосіб зробити це в Angular. :)
Лукачі Андрій

Допоміг мені там, де у мене був єдиний список і змінивши одне значення не слід оновлювати наступне, тому це допомогло використовувати це як хак без використання ngmodel, спасибі :)
Мелвін

Це працює для простих об’єктів JavaScript, але зауважте, що для примірників класу ви втратите всі методи на ньому.
ХалилРаванна

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>

На компонент.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>

На компонент.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

Крім того, якщо нічого із заданих рішень не працює, перевірте, чи ви імпортували "FormsModule" всередині "AppModule", це було для мене ключовим.


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>

У ц:

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>

такий підхід завжди працюватиме, однак якщо у вас є динамічний список, обов’язково завантажте його перед моделлю

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.