我正试图获得一个带有复选框的多选下拉列表,在填充项目和获得所有选中的工作时遇到了一些问题

I am trying to get a multiselect dropdown with checkbox, facing some issue while populating items and getting allChecked work

本文关键字:填充 项目 问题 遇到 工作 一个 下拉列表 复选框      更新时间:2024-03-17

我跟踪了一个小提琴

使用多选

并对其进行了修改。我的小提琴-改良Fiddle

我正在使用它来选择下拉菜单中的All/DeselectAll功能。我已经将Items数组设置为可观察的,并推送从服务器返回的值。

我哪里做错了。

function CheckableBox(label, isChecked) {
  this.label = label;
  this.isChecked = ko.observable(isChecked || false);
}
var authTypeArray = [{name:'All Therapy''},{name:'P Therapy''},{name:'O Therapy'},{name:'S Therapy'},{name:'R Therapy'}];
function ViewModel() {
	this.Items = ko.observableArray();
  this.specialtyViewArray = authTypeArray;
  for (var id = 0; id < this.specialtyViewArray.length; id++) {
    var name = this.specialtyViewArray[id].name;
    this.Items.push(new CheckableBox(name, false));
  }
  
  this.selectedItems = ko.observable([]);
	/* Includes only the checked items */
  this.tempSelection = ko.pureComputed(function() {
    return this.Items.filter(function(item) {
      return item.isChecked();
    });
  }, this);
  
  /* Builds a comma separated string of selected items */
  this.selectedItemsStr = ko.pureComputed(function() {
  	var str = this.selectedItems()
    	.map(function(item) {
      	return item.label;
      })
      .join(", ")
      
      return str || "-- No options selected --";
  }, this);
  
  /* Determines whether the selectable options are displayed. */
  this.optionsShown = ko.observable(false);
  
  this.optionsShown.subscribe(function() {
  	this.updateSelections();
  }, this);
  
  this.confirmSelection();
  this.checkAll = ko.computed({
    read: function () {
      var firstUnchecked = ko.utils.arrayFirst(this.Items(), function (item) 										{
        return item.isChecked(false);
      });
      return firstUnchecked == null;
    },
    write: function (value) {
      ko.utils.arrayForEach(this.Items(), function (item) {
       item.isChecked(value);
      });
    }
  });
};
ViewModel.prototype.toggleOptions = function() {
	this.optionsShown(!this.optionsShown());
};
ViewModel.prototype.confirmSelection = function() {
	this.selectedItems(this.tempSelection());
  this.closeOptions();
};
ViewModel.prototype.closeOptions = function() {
  this.optionsShown(false);
}
ViewModel.prototype.updateSelections = function() {
	var selection = this.selectedItems();
  this.Items.forEach(function(item) {
    item.isChecked(selection.indexOf(item));
  });
}
ko.applyBindings(new ViewModel());
* {
  box-sizing: border-box;
  font-family: sans-serif;
}
.main-container {
  width: 400px;
}
.main-container,
.select-container {
  position: relative;
}
.select-container {
  height: 2em;
}
select,
.select-container::after {
  width: 100%;
  height: 100%;
}
.select-container::after {
  content: "";
  position: absolute;
  top: 0;
  background: rgba(0,0,0,0);
}
.options-container {
  position: absolute;
  top: 2em;
  width: 100%;
  border: 1px solid #A9A9A9;
  background: #FFFFFF;
  display: none;
}
.options-container.shown {
  display: block;
}
label {
  display: block;
  padding: .2em;
}
label:not(:last-child) {
  border-bottom: 1px solid #FFFFFF;
}
.checked {
  background: #568ECB;
  color: white;
}
.button-container {
  display: flex;
  justify-content: flex-end;
  border-top: 1px solid #A9A9A9;
  background: #F6F6F6;
}
.button-container button {
  margin: .4em;
  margin-left: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class="main-container">
  <div class="select-container" data-bind="click: toggleOptions">
    <select data-bind="options: [selectedItemsStr]"></select>
  </div>
  <div class="options-container" data-bind="css: { 'shown': optionsShown }">
    <div class="options" data-bind="foreach: Items">
      <!-- ko if: $index() == 0 -->
      <label data-bind="css: { 'checked': isChecked }">
        <input type="checkbox" data-bind="checked: checkAll">
        <span data-bind="text: label"></span>
      </label>
      <!-- /ko -->
      <!-- ko if: $index() != 0 -->
      <label data-bind="css: { 'checked': isChecked }">
        <input type="checkbox" data-bind="checked: isChecked">
        <span data-bind="text: label"></span>
      </label>
      <!-- /ko -->
    </div>
    <div class="button-container">
      <button type="button" data-bind="click: confirmSelection">OK</button>
      <button type="button" data-bind="click: closeOptions">Cancel</button>
    </div>
  </div>
</div>

您犯了很多错误:

name:'All Therapy''什么是?

this.Items-您定义了类似observableArray(函数)的变量,但试图将类似this.Items.filter 的数组方法应用于它

在您的计算函数中,您有错误的上下文。您可以使用所有者选项。

在您的html模板中,您有未定义的绑定

<input type="checkbox" data-bind="checked: checkAll">

checkAll在您的CheckableBox模型中不存在。您需要使用$parent.checkAll

这里简单的工作代码:

function CheckableBox(label, isChecked) {
  this.label = label;
  this.isChecked = ko.observable(isChecked || false);
}
function ViewModel(data) {
  this.items = data.map(function(item) {
      return new CheckableBox(item.name, false);
  });
  this.selectedItems = ko.observable([]);
  this.tempSelection = ko.pureComputed(function() {
    return this.items.filter(function(item) {
      return item.isChecked();
    });
  }, this);
  this.selectedItemsStr = ko.pureComputed(function() {
    var str = this.selectedItems()
      .map(function(item) {
        return item.label;
      })
      .join(", ")
      return str || "-- No options selected --";
  }, this);
  this.optionsShown = ko.observable(false);
  this.optionsShown.subscribe(function() {
    this.updateSelections();
  }, this);
  this.confirmSelection(); 
  this.checkAll = ko.pureComputed({
    read: function () {
      return this.items.every(function(item) {
        return item.isChecked();
      });
    },
    write: function (value) {
      this.items.forEach(function (item) {
        item.isChecked(value);
      });
    },
    owner: this
  });
};
ViewModel.prototype.toggleOptions = function() {
  this.optionsShown(!this.optionsShown());
};
ViewModel.prototype.confirmSelection = function() {
  this.selectedItems(this.tempSelection());
  this.closeOptions();
};
ViewModel.prototype.closeOptions = function() {
  this.optionsShown(false);
};
ViewModel.prototype.updateSelections = function() {
  var selection = this.selectedItems();
  this.items.forEach(function(item) {
    item.isChecked(~selection.indexOf(item));
  });
};
var authTypeArray = [
  { name:'All Therapy' },
  { name:'P Therapy' },
  { name:'O Therapy' },
  { name:'S Therapy' },
  { name:'R Therapy' }
];
ko.applyBindings(new ViewModel(data));

我希望这对你有帮助。我修改的Fiddle