2015-10-17 6 views
39

Sto riscontrando problemi nella creazione di una selezione in Angular2 supportata da una matrice di oggetti anziché stringhe. Sapevo come farlo in AngularJS usando ngOptions, ma non sembra funzionare in Angular2 (sto usando alpha 42).Come utilizzare select/option/NgFor su una matrice di oggetti in Angular2

Nell'esempio seguente, ho quattro selezioni, ma solo due funzionano.

  1. 'Select String' è una semplice selezione basata su stringhe e funziona correttamente.
  2. 'Seleziona oggetto tramite rilegatura bidirezionale' era il mio tentativo di utilizzare il binding a 2 vie. Sfortunatamente, fallisce in due modi: quando la pagina viene caricata, la selezione mostra il valore sbagliato (pippo invece di barra), e quando seleziono un'opzione nell'elenco, il valore '[Oggetto oggetto]' viene inviato al backing store invece del valore corretto.
  3. 'Seleziona oggetto tramite evento' è stato il mio tentativo di ottenere il valore selezionato da $ event. Fallisce anche in due modi: il caricamento iniziale non è corretto allo stesso modo del # 2 e quando seleziono un'opzione nell'elenco, il valore '[oggetto oggetto]' viene recuperato dall'evento, quindi non posso ottieni il giusto valore La selezione viene cancellata.
  4. 'Seleziona oggetto tramite stringa' è l'unico approccio che utilizza un oggetto che funziona. Sfortunatamente, funziona davvero usando l'array di stringhe da # 1 e convertendo il valore da una stringa all'oggetto e viceversa.

posso fare # 4 se questo è il modo previsto, ma sembra piuttosto goffo. C'è un altro approccio? Sono troppo presto nell'alfa? Ho fatto qualcosa di sciocco?

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); 
    } 
} 
+5

Cari viaggiatori del tempo di venire qui nel 2016 o dopo! La [domanda collegata] (http://stackoverflow.com/q/35945001) ha una [risposta migliore] (http://stackoverflow.com/a/35945293) che non usa hacky object-to-json-to- conversione di oggetti. –

+0

Vero. È strano, tuttavia, che questo sia stato contrassegnato come un duplicato dell'altro quando questa domanda è anteriore all'altra di 5 mesi. – user3221325

risposta

15

Non sono un esperto con DOM o JavaScript/tipografico, ma penso che il DOM-Tag non può gestire oggetto reale javascript in qualche modo. Ma mettendo l'intero oggetto in forma di stringa e l'analisi di nuovo a un oggetto/JSON ha funzionato per me:

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); 
    } 
} 
+2

Grazie. Non l'ho provato, ma sembra che funzionerebbe. È ancora non ovvio e goffo, quindi spero che il team ng2 abbia un approccio più diretto, ma è una scelta definitiva. – user3221325

+0

Grazie per il vostro aiuto. Ho postato questa domanda (con il tuo esempio aggiunto) alla lista delle domande: https://github.com/angular/angular/issues/4843 – user3221325

+0

BTW, con Angular2, l'evento si presenta come un oggetto quindi 'updateSelectedValue (event: string) 'La funzione deve essere cambiata in' updateSelectedValue (event: Object) 'e l'intestino della funzione deve essere modificato in' this.selectedObject = JSON.parse (event.target.value); ' – RHarris

33

Non so ciò che le cose erano come in alpha, ma sto usando beta 12 a destra ora e questo funziona bene. Se si dispone di un array di oggetti, creare un selezionare come questo:

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

Se si desidera far corrispondere l'oggetto reale, lo farei in questo modo:

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

Il binding funziona quando l'utente seleziona un elemento nell'elenco. Tuttavia, l'elemento selezionato non viene mostrato correttamente quando la pagina viene caricata. Potete fornire un plunker per un esempio di lavoro? – AustinTX

+2

Impossibile collegarsi a "ngModel" poiché non è una proprietà nota di "seleziona". Questo è ciò che ottengo – John

+1

Probabilmente è necessario importare il moduloModule – carrizal