Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding select element to object in Angular

Tags:

html

angular

I'd like to bind a select element to a list of objects -- which is easy enough:

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

In this case, it appears that selectedValue would be a number -- the id of the selected item.

However, I'd actually like to bind to the country object itself so that selectedValue is the object rather than just the id. I tried changing the value of the option like so:

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

but this does not seem to work. It seems to place an object in my selectedValue -- but not the object that I'm expecting. You can see this in my Plunker example.

I also tried binding to the change event so that I could set the object myself based on the selected id; however, it appears that the change event fires before the bound ngModel is updated -- meaning I don't have access to the newly selected value at that point.

Is there a clean way to bind a select element to an object with Angular 2?

like image 630
RHarris Avatar asked Mar 11 '16 16:03

RHarris


3 Answers

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

StackBlitz example

NOTE: you can use [ngValue]="c" instead of [ngValue]="c.id" where c is the complete country object.

[value]="..." only supports string values
[ngValue]="..." supports any type

update

If the value is an object, the preselected instance needs to be identical with one of the values.

See also the recently added custom comparison https://github.com/angular/angular/issues/13268 available since 4.0.0-beta.7

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

Take care of if you want to access this within 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;
}
like image 146
Günter Zöchbauer Avatar answered Oct 18 '22 12:10

Günter Zöchbauer


This could help:

<select [(ngModel)]="selectedValue">
  <option *ngFor="#c of countries" [value]="c.id">{{c.name}}</option>
</select>
like image 53
Carolina Faedo Avatar answered Oct 18 '22 14:10

Carolina Faedo


You can do this too without the need to use [(ngModel)] in your <select> tag

Declare a variable in your ts file

toStr = JSON.stringify;

and in you template do this

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

and then use

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

to parse the string back into a valid JavaScript object

like image 23
Rahul Kumar Avatar answered Oct 18 '22 13:10

Rahul Kumar