Подтвердить что ты не робот

Как использовать select/option/NgFor для массива объектов в Angular2

Мне не удается создать выбор в Angular2, который поддерживается массивом объектов вместо строк. Я знал, как это сделать в AngularJS, используя ngOptions, но он не работает в Angular2 (я использую альфа 42).

В приведенном ниже примере у меня есть четыре выбора, но только два из них работают.

  • 'Select String' - это простой выбор на основе строк, и он отлично работает.
  • "Выбрать объект с помощью двусторонней привязки" была моя попытка использовать двустороннюю привязку. К сожалению, он не срабатывает двумя способами: при загрузке страницы выбор показывает неправильное значение (foo вместо bar), а когда я выбираю опцию в списке, значение "[Object Object]" отправляется в хранилище резервных копий вместо правильного значения.
  • "Выбрать объект через событие" была моя попытка получить выбранное значение из $event. Сбой также невозможен двумя способами: начальная загрузка неверна так же, как и # 2, и когда я выбираю опцию в списке, значение "[Объект объекта]" извлекается из события, поэтому я не могу получить правильное значение. Выбор будет очищен.
  • "Выбрать объект через строку" - единственный подход, который использует объект, который работает. К сожалению, это действительно работает с использованием строкового массива из # 1 и преобразования значения из строки в объект и обратно.

Я могу сделать # 4, если это намеченный путь, но кажется довольно неуклюжим. Есть ли другой подход? Я слишком рано в альфе? Я сделал что-то глупое?

import {Component, FORM_DIRECTIVES, NgFor} from 'angular2/angular2';

interface TestObject {
  name:string;
  value:number;
}

@Component({
  selector: 'app',
  template: `
    <h4>Select String</h4>
    <select [(ng-model)]="strValue">
        <option *ng-for="#o of strArray" [value]="o">{{o}}</option>
    </select>

    <h4>Select Object via 2-way binding</h4>
    <select [(ng-model)]="objValue1">
        <option *ng-for="#o of objArray" [value]="o">{{o.name}}</option>
    </select>

    <h4>Select Object via event</h4>
    <select [ng-model]="objValue2" (change)="updateObjValue2($event)">
        <option *ng-for="#o of objArray" [value]="o">{{o.name}}</option>
    </select>

    <h4>Select Object via string</h4>
    <select [ng-model]="objValue3.name" (change)="updateObjValue3($event)">
        <option *ng-for="#o of strArray" [value]="o">{{o}}</option>
    </select>

    <div><button (click)="printValues()">Print Values</button></div>

  `,
  directives: [FORM_DIRECTIVES, NgFor]
})
export class AppComponent {
  objArray:TestObject[] = [{name: 'foo', value: 1}, {name: 'bar', value: 1}];
  objValue1:TestObject = this.objArray[1];
  objValue2:TestObject = this.objArray[1];
  objValue3:TestObject = this.objArray[1];

  strArray:string[] = this.objArray.map((obj:TestObject) => obj.name);
  strValue:string = this.strArray[1];

  updateObjValue2(event:Event):void {
    const value:string = (<HTMLSelectElement>event.srcElement).value;

    this.objValue2 = this.objArray.find((obj:TestObject) => obj.name === value);
  }

  updateObjValue3(event:Event):void {
    const value:string = (<HTMLSelectElement>event.srcElement).value;

    this.objValue3 = this.objArray.find((obj:TestObject) => obj.name === value);
  }

  printValues():void {
    console.log('strValue', this.strValue);
    console.log('objValue1', this.objValue1);
    console.log('objValue2', this.objValue2);
    console.log('objValue3', this.objValue3);
  }
}
4b9b3361

Ответ 1

Я не знаю, что было в альфа, но сейчас я использую бета-версию 12, и это отлично работает. Если у вас есть массив объектов, создайте выделение следующим образом:

<select [(ngModel)]="simpleValue"> // value is a string or number
    <option *ngFor="#obj of objArray" [value]="obj.value">{{obj.name}}</option>
</select>

Если вы хотите совпадать с фактическим объектом, я бы сделал это следующим образом:

<select [(ngModel)]="objValue"> // value is an object
    <option *ngFor="#obj of objArray" [ngValue]="obj">{{obj.name}}</option>
</select>

Ответ 2

Я не эксперт с DOM или Javascript/ Typescript, но я думаю, что DOM-теги каким-то образом не могут обрабатывать реальный объект javascript. Но, поставив весь объект в виде строки и разобрав его обратно в Object/JSON, я работал у меня:

interface TestObject {
  name:string;
  value:number;
}

@Component({
  selector: 'app',
  template: `
      <h4>Select Object via 2-way binding</h4>

      <select [ngModel]="selectedObject | json" (ngModelChange)="updateSelectedValue($event)">
        <option *ngFor="#o of objArray" [value]="o | json" >{{o.name}}</option>
      </select>

      <h4>You selected:</h4> {{selectedObject }}
  `,
  directives: [FORM_DIRECTIVES]
})
export class App {
  objArray:TestObject[];
  selectedObject:TestObject;
  constructor(){
    this.objArray = [{name: 'foo', value: 1}, {name: 'bar', value: 1}];
    this.selectedObject = this.objArray[1];
  }
  updateSelectedValue(event:string): void{
    this.selectedObject = JSON.parse(event);
  }
}