Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SELECT --> OPTION, using value vs ngValue

I just recently figured out that there is an alternative for value property on OPTION part of the SELECT, namely ngValue. The docs really lack documentation about this (all I could find: https://angular.io/docs/ts/latest/api/forms/index/NgSelectOption-directive.html). Anyway, the idea is that when you use an object for the ngModel, you can use ngValue and it works well. Otherwise, only e.g. ID is updated. If we're having just an array of strings, value is sufficient. Here are the examples:

{{myModel | json}}
<select [(ngModel)]="myModel">
  <option *ngFor="let i of items" [ngValue]="i">{{i.value}}</option>
</select>

<br /><br />

{{mySimpleModel}}
<select [(ngModel)]="mySimpleModel">
  <option *ngFor="let i of simpleItems" [value]="i">{{i}}</option>
</select>

While this works as expected, there's a distinctive differences between the two: if using ngValue, the predefined value is not selected in the drop down, whereas for the primitive types, the value is selected on loading. E.g.:

items: any[] = [{id: 1, value: 'item1'}, {id: 2, value: 'item2'}, {id: 3, value: 'item3'}];
myModel: any = {id: this.items[1].id , value: this.items[1].value};

simpleItems: string[] = ['item1', 'item2', 'item3'];
mySimpleModel: string = this.simpleItems[1];  

See example here: https://plnkr.co/edit/JBrtmx7QkPZztBjaqYkS?p=preview So, why does Angular set the default value for strings, but not for objects? And what is the most elegant workaround?

like image 524
uglycode Avatar asked Apr 16 '17 22:04

uglycode


1 Answers

You don't need a "workaround" for that. When you do this

myModel = {id: this.items[1].id , value: this.items[1].value};

you are creating a new object which has the same values as this.items[1] but it is not the same object, it's a new one.

const items = [{id: 1, value: 'item1'}, {id: 2, value: 'item2'}, {id: 3, value: 'item3'}]

const myModel = {id: 2, value: 'item2'};

console.log(items[1] === myModel);

that is the reason why your select can't find that value in the <option> list.

In order to fix that, you have to use a proper reference

items = [
     {id: 1, value: 'item1'},
     {id: 2, value: 'item2'},
     {id: 3, value: 'item3'}
];
myModel = this.items[1]

plunkr

like image 117
QoP Avatar answered Oct 19 '22 22:10

QoP