如何在Angular2中的对象数组上使用select / option / NgFor

时间:2015-10-17 01:58:21

标签: typescript angular

我在Angular2中创建一个由Object数组而不是字符串支持的选择时遇到了问题。我知道如何使用ngOptions在AngularJS中执行此操作,但它似乎不适用于Angular2(我使用alpha 42)。

在下面的示例中,我有四个选择,但只有两个选择。

  1. '选择字符串'是一个简单的基于字符串的选择,它工作正常。
  2. '通过双向绑定选择对象'是我尝试使用双向绑定。不幸的是,它以两种方式失败 - 当页面加载时,select显示错误的值(foo而不是bar),当我在列表中选择一个选项时,值' [object Object]'被发送到后备存储而不是正确的值。
  3. '通过活动选择对象'是我尝试从$ event获取所选值。它也以两种方式失败 - 初始加载与#2一样不正确,当我在列表中选择一个选项时,值' [object Object]'从事件中检索,所以我无法获得正确的价值。选择被清除。
  4. '通过字符串选择对象'是唯一使用有效对象的方法。不幸的是,它确实可以通过使用#1中的字符串数组并将值从string转换为object并返回。
  5. 如果这是预期的方式我可以做#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);
      }
    }
    

2 个答案:

答案 0 :(得分:44)

我不知道alpha中的内容是什么样的,但我现在正在使用beta 12,这很好用。如果您有一个对象数组,请创建一个这样的选择:

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

如果你想匹配实际的对象,我就这样做:

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

答案 1 :(得分:17)

我不是DOM或Javascript / Typescript的专家,但我认为DOM-Tags无法以某种方式处理真正的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);
  }
}