I'm able to bind using ngModel for a single select but I would like to bind an array to the multiple selected options. When I attempt this I get the error
Cannot find a differ supporting object 'xxx' in 'myModelProperty'
My Code
<select multiple [(ngModel)]="myModelProperty">
<option *ngFor="#item of myOptions" [value]="item.value">{{item.name}}</option>
</select>
Why all those complicate answers about simple question.
If you in advance have options which have to be selected, you can do it simply this way :
This code is good :
HTML
<select multiple [(ngModel)]="myModelProperty">
<option *ngFor="#item of myOptions" [value]="item.value">{{item.name}}</option>
</select>
ANGULAR
myModelProperty: any;
myModelProperty = ['YOUR_VALUE', 'YOUR_VALUE'];
or if you have string, you can parse it
myModelProperty: any;
myModelProperty = string.split(',');
So, all you have to done is that [(ngModel)] from select tag, have to be initialized in angular part with some array of values which correspond to [value] from option tag
This will automatically select one or more options depends on values from array.
Here's a multi-select list implementation that supports two-way databinding. I use @ViewChild instead of getElementById().
@Component({
selector: 'my-app',
template: `{{title}}<p>
<select #select multiple (change)="change($event.target.options)">
<option *ngFor="#item of myOptions" [value]="item.value">
{{item.name}}
</option>
</select>
<br><button (click)="changeOptions()">select 1 and 3</button>
<p>{{selectedValues | json}}`
})
export class AppComponent {
@ViewChild('select') selectElRef;
title = "Angular 2 beta - multi select list";
myOptions = [
{value: 1, name: "one"},
{value: 2, name: "two"},
{value: 3, name: "three"}];
selectedValues = ['1','2'];
myModelProperty = this.myOptions[0];
constructor() { console.clear(); }
ngAfterViewInit() {
this.updateSelectList();
}
updateSelectList() {
let options = this.selectElRef.nativeElement.options;
for(let i=0; i < options.length; i++) {
options[i].selected = this.selectedValues.indexOf(options[i].value) > -1;
}
}
change(options) {
this.selectedValues = Array.apply(null,options) // convert to real Array
.filter(option => option.selected)
.map(option => option.value)
}
changeOptions() {
this.selectedValues = ['1','3'];
this.updateSelectList();
}
}
Whenever the selectedValues property is changed by some component logic, updateSelectList() must also be called, as is shown in the "select 1 and 3" button callback logic.
For easier reuse, this should probably be refactored into an attribute directive. (Any takers?)
As others have said, it's not supported by default in Angular2 yet. I thought to post this, it seems rather much simpler workaround. Here is a sample HTML:
<select multiple (change)="setSelected($event.target)">
<option *ngFor="#item of myOptions" [value]="item.value">{{item.name}}</option>
</select>
And myClass with a setSelected function:
...
export class myClass {
...
myOptions: [];
...
setSelected(selectElement) {
for (var i = 0; i < selectElement.options.length; i++) {
var optionElement = selectElement.options[i];
var optionModel = this.myOptions[i];
if (optionElement.selected == true) { optionModel.selected = true; }
else { optionModel.selected = false; }
}
}
}
...
Any time you need a reference to selected items, you can use:
var selectedItems = this.myOptions.filter((item) => { return item.selected === true; });