Enlace seleccionar elemento a objeto en Angular


Soy nuevo en Angular y estoy tratando de ponerme al día con la nueva forma de hacer las cosas.

Me gustaría enlazar un elemento select a una lista de objetos which lo cual es bastante fácil:

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

En este caso, parece que SelectedValue sería un número id el id del elemento seleccionado.

Sin embargo, me gustaría enlazar al objeto country en sí para que SelectedValue sea el objeto en lugar de solo el id. Intenté cambiar el valor de la opción como entonces:

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

Pero esto no parece funcionar. Parece que para colocar un objeto en mi selectedValue --, pero no el objeto que estoy esperando. Puedes ver esto en mi ejemplo de Émbolo.

También intenté enlazar al evento de cambio para poder establecer el objeto yo mismo en función del id seleccionado; sin embargo, parece que el evento de cambio se activa antes de que se actualice el ngModel enlazado, lo que significa que no tengo acceso al valor recién seleccionado en ese momento.

Hay un ¿forma limpia de enlazar un elemento select a un objeto con Angular 2?

 267
Author: Lazar Ljubenović, 2016-03-11

9 answers

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

Ejemplo de StackBlitz

NOTA: puede usar [ngValue]="c" en lugar de [ngValue]="c.id" donde c es el objeto country completo.

[value]="..." solo admite valores de cadena
[ngValue]="..." soporta cualquier tipo

Update

Si el value es un objeto, la instancia preseleccionada debe ser idéntica a uno de los valores.

Consulte también la comparación personalizada recientemente añadida https://github.com/angular/angular/issues/13268 disponible desde 4.0.0-beta.7

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

Tenga cuidado si desea acceder a this dentro de compareFn.

compareFn = this._compareFn.bind(this);

// or 
// compareFn = (a, b) => this._compareFn(a, b);

_comareFn((a, b) {
   if(this.x ...) {
     ...
}
 493
Author: Günter Zöchbauer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-19 07:27:35

Esto podría ayudar:

<select [(ngModel)]="selectedValue">
      <option *ngFor="#c of countries" [value]="c.id">{{c.name}}</option>
</select>
 29
Author: Carolina Faedo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-15 14:41:36

También puede hacer esto sin la necesidad de usar [(ngModel)] en su etiqueta <select>

Declare una variable en su archivo ts

toStr = JSON.stringify;

Y en tu plantilla haz esto

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

Y luego use

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

Para analizar la cadena de nuevo en un objeto JavaScript válido

 12
Author: Rahul Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-04 05:36:00

Puede seleccionar el Id usando una Función

<option *ngFor="#c of countries" (change)="onchange(c.id)">{{c.name}}</option>
 5
Author: Eng.Gabr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-24 10:05:13

Funcionó para mí: {[14]]}

Plantilla HTML:

He añadido (ngModelChange)="selectChange($event)" a mi 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>

En el componente.ts:

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

An necesita agregar a component.ts esta función:

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

Nota: Intento con [select]="oneOption.id==model.myListOptions.id" y no trabajo.

============= Otras formas pueden ser: =========

Plantilla HTML:

He añadido [compareWith]="compareByOptionId a mi 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>

En el componente.ts:

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

An necesita agregar a component.ts esta función:

 /* Return true or false if it is the selected */
 compareByOptionId(idFist, idSecond) {
    return idFist && idSecond && idFist.id == idSecond.id;
 }
 5
Author: Jose Carlos Ramos Carmenates,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-29 00:32:06

Para mí funciona así, puedes consolar event.target.value.

<select (change) = "ChangeValue($event)" (ngModel)="opt">   
    <option *ngFor=" let opt of titleArr" [value]="opt"></option>
</select>
 4
Author: Shubhranshu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-24 07:54:28

En caso de que alguien esté buscando hacer lo mismo usando Formularios Reactivos:

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

Compruebe el ejemplo de trabajo aquí

 3
Author: elvin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-05 20:56:03

Además, si nada más de las soluciones dadas no funciona, verifique si importó "FormsModule" dentro de "AppModule", esa fue una clave para mí.

 2
Author: nikola.maksimovic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-14 21:24:17

Puede obtener el valor seleccionado también con la ayuda de click() pasando el valor seleccionado a través de la función

<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>
 1
Author: Jose Kj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-25 11:40:33