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
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.
You could implement your own like in my plnkr. UPDATED because CHOW wanted the example without jquery.
http://plnkr.co/edit/Pf92XATg3PT5RtBvrsaA?p=preview
//our root app component
import {Component} from 'angular2/core'
@Component({
selector: 'my-app',
providers: [],
styles:['.options{cursor:pointer;padding:10px;border-bottom:1px solid black;}', '.multiple-select{overflow-y:scroll; height:100px;}'],
template: `
<h3>{{selected|json}}</h3>
<div class="multiple-select col-lg-6 col-md-6 col-sm-6 col-xs-6" style="">
<div class="options col-lg-12 col-md-12 col-xs-12 col-sm-12" *ngFor="#athlete of athletes" id={{athlete.id}} (click)="toggleMultiSelect($event, athlete)">{{athlete.name}}</div>
</div>
`,
directives: []
})
export class App {
public athletes:any[]=[];
public selected:any[]=[];
constructor() {
for(var i = 1; i <= 5; i++){
this.athletes.push({
value:i,
name:("athlete-"+i),
id:("id-"+i)
})
}
}
toggleMultiSelect(event, val){
event.preventDefault();
if(this.selected.indexOf(val) == -1){
this.selected = [...this.selected, val];
var elem = document.getElementById(val.id);
elem.className += " fa fa-check";
}else{
var elem = document.getElementById(val.id);
elem.className = elem.className.split(' ').splice(0, elem.className.split(' ').length - 2).join(' ');
this.selected = this.selected.filter(function(elem){
return elem != val;
})
}
}
}
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();
}
}
Plunker
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?)
Another way to chose/Select multiple option using pure javascript in angular2. here is the code we have to write in .html file:
<div class="multiselect">
<div class="selectBox(click)="showCheckboxes('checkboxes1',batchEvent); batchEvent=!batchEvent">
<select class="form-control">
<option selected disabled>Select Batch</option>
</select>
<div class="overSelect"></div>
</div>
<div id="checkboxes1" style="display: none;">
<div *ngFor="#batch of batch_array">
<input type="checkbox" [value]="batch.id" id="E{{batch.id}}" (click)="batchSelectedEevent('E'+batch.id,batch.id)" /> {{batch.batch_name}}
</div>
</div>
</div>
css is here:-
.multiselect {
width: 200px;
}
.selectBox {
position: relative;
}
.selectBox select {
width: 100%;
font-weight: bold;
}
.overSelect {
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
}
in the .ts file or in the constructor we have to write:
batchEvent:boolean= false;
// Function for Multiple Select options checkbox area //
showCheckboxes(ids, flag) {
let checkboxes = document.getElementById(ids);
if (!flag) {
checkboxes.style.display = "block";
} else {
checkboxes.style.display = "none";
}
}
batchSelectedholiday(id, value) {
// console.log(id, value);
if ((<HTMLInputElement>document.getElementById(id)).checked == true) {
this.batchHoliday_array.push(value);
}
else if ((<HTMLInputElement>document.getElementById(id)).checked == false) {
let indexx = this.batchHoliday_array.indexOf(value);
this.batchHoliday_array.splice(indexx, 1);
}
console.log(this.batchHoliday_array, "batchHoliday_array");
}
Use ng-select
<ng-select [multiple]="true" [items]="items" (selected)="selected($event)"
(removed)="removed($event)" placeholder="Select the technologies" required>
</ng-select>
here items are an array that you want to display as list.remove
event fire when you deselect the selected element.selected
element fired when you select something from the array-items
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; });