Angular2:如何绑定到选择多个

33

我能够使用ngModel绑定单选,但我想将数组绑定到多个选项上。当我尝试这样做时,出现以下错误:

无法在“myModelProperty”中找到支持对象“xxx”的区别。

我的代码

<select multiple [(ngModel)]="myModelProperty">
    <option *ngFor="#item of myOptions" [value]="item.value">{{item.name}}</option>
</select>

1
请参见 https://github.com/angular/angular/issues/4427。 - Mark Rajcok
我在我的Angular2代码中使用了这个(https://dev59.com/XWMm5IYBdhLWcg3wT9mU#27547021),如果你需要Angular2的代码,我会发布它。 - Pardeep Jain
似乎还没有实现;https://github.com/angular/angular/issues/6830 - Honorable Chow
请查看PrimeNG Listbox,它有多种模式。http://www.primefaces.org/primeng/#/listbox - Cagatay Civici
7个回答

23

为什么针对简单问题要回答那么复杂呢?

如果你提前有必须选择的选项,可以用以下简单的方式:

这段代码是好的

HTML

<select multiple [(ngModel)]="myModelProperty">
    <option *ngFor="#item of myOptions" [value]="item.value">{{item.name}}</option>
</select>

ANGULAR

->

ANGULAR

myModelProperty: any;
myModelProperty = ['YOUR_VALUE', 'YOUR_VALUE'];

如果您有 字符串,您可以解析它。

myModelProperty: any;
myModelProperty = string.split(',');

所以,您需要做的就是在 Angular 部分使用与 [value] 相对应的一些值数组来初始化来自选择标签的[(ngModel)]

这将根据数组中的值自动选择一个或多个选项。


不幸的是,这种方法在页面加载时不会将所选选项标记为已选择。即与“myModelProperty”中的条目对应的选项未设置“selected”属性。 - bleistift2
使用for循环的所选属性和索引来添加一个条件,使其评估为真。 - Gabriel Luca

20

这里有一个支持双向数据绑定的多选列表实现。我使用@ViewChild而不是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

每当selectedValues属性被某个组件逻辑所改变时,updateSelectList()也必须被调用,这在"select 1 and 3"按钮回调逻辑中有展示。

为了更容易重用,这应该被重构为一个属性指令。(有人接手吗?)


12

正如其他人所说,目前Angular2默认不支持此功能。我想发布这篇文章,因为有一个相当简单的解决方法。以下是一个示例HTML代码:

<select multiple (change)="setSelected($event.target)">
    <option *ngFor="#item of myOptions" [value]="item.value">{{item.name}}</option>
</select>

有一个带有 setSelected 函数的 myClass

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

每当你需要引用所选项目时,你可以使用:

var selectedItems = this.myOptions.filter((item) => { return item.selected === true; });

3
你可以像我在plnkr中的示例一样自己实现。 更新,因为CHOW想要没有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;
      })
    }
  }
}

http://imgur.com/2P383hS


在Ubuntu Linux上出现“e.values不是函数”的错误。 - Pardeep Jain
我的电脑上运行得非常好,而且我还有一个chrome笔记本双启动Ubuntu。 - inoabrian
谢谢您的回复,我很感激您的努力,但是那种 jQuery 不应该出现在控制器/视图模型中。您已经违反了关注点分离原则。 - Honorable Chow

1

使用纯JavaScript在Angular2中选择/选择多个选项的另一种方法。这里是我们必须在.html文件中编写的代码:

   <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在这里:

.multiselect {
        width: 200px;
    }
    .selectBox {
        position: relative;
    }
    .selectBox select {
        width: 100%;
        font-weight: bold;
    }
    .overSelect {
        position: absolute;
        left: 0; right: 0; top: 0; bottom: 0;
    }

在.ts文件或构造函数中,我们必须编写:
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");
    }

1
使用 ng-select
<ng-select [multiple]="true" [items]="items" (selected)="selected($event)"
                        (removed)="removed($event)" placeholder="Select the technologies" required>
</ng-select>

这里的items是一个数组,你想将其显示为列表。当你取消选择已选中的element.selected元素时,触发list.remove事件。当你从数组项中选择某个元素时,触发element.selected事件。


0

虽然时间有点久远,但我会回答的。这对我很有帮助。

HTML

<select multiple [(ngModel)]="myModelProperty">
<option *ngFor="#item of myOptions" [value]="item.value">{{item.name}}</option>

ts

myModelProperty: any;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接