Knockout / Select2下拉列表包含正确的选项,但现在不显示任何内容

因此,我有两个下拉列表供我使用,并用于剔除和选择。当availablePeople列表返回所有false(不能正常工作)时,我可以选择并保留我选择的人。但是,当可用人员列表正常工作时,我看不到我选择的下拉菜单。要详细说明可用的人员列表,如果您选择一个人,则该人将不再可以在以后的行中选择。

的HTML

<div>
  <table id="tblPossessionChanges">
    <thead>
      <tr>
        <th><a href="#" class="buttonSmall" data-bind="click: addPossessionChange">Add</a></th>
        <th>From</th>
        <th>To</th>
      </tr>
    </thead>
    <tbody data-bind="foreach: PossessionChanges">
      <tr>
        <td class="prompt">
          <a href="#" class="buttonSmall" data-bind="click: $root.removePossessionChange">Delete</a>           </td>
        <td>
          <select class="form-control" 
                  data-bind="options: $root.AvailableFrom, 
                             value: SelectedFrom,
                             optionsText: function(i) {return i.Name}, 
                             optionsValue: function(i) {return i.ID},
                             optionsCaption: 'Please select a Person...',
                             select2: { placeholder: 'Please select a Person...', allowClear: false}">             </select>
        </td>
        <td>
          <select class="form-control"
                  data-bind="options: $root.AvailableTo, 
                             value: SelectedTo, 
                             optionsText: function(i) {return i.Name}, 
                             optionsValue: function(i) {return i.ID},
                             optionsCaption: 'Please select a Person...',
                             select2: {placeholder: 'Please select a Person...', allowClear: false}">            </select>
        </td>
        <td>
          <span id="changeTypeSpan" data-bind="text: ChangeType"></span>
        </td>
      </tr>
    </tbody>
  </table>
</div>

JS

 ko.bindingHandlers.select2 = {
    init: function (element, valueAccessor, allBindingsAccessor, bindingContext) {
      ko.utils.domNodeDisposal.addDisposeCallback(element,
        function() {
          $(element).select2('destroy');
        });
      var select2 = ko.utils.unwrapObservable(allBindingsAccessor().select2);
      $(element).select2(select2);
    },
    update: function (element, valueAccessor, allBindingsAccessor, bindingContext) {
      var allBindings = allBindingsAccessor();
      if ("value" in allBindings) {
        if ((allBindings.select2.multiple || element.multiple) && allBindings.value().constructor != Array) {
          $(element).val(allBindings.value().split(',')).trigger('change');
        } else {
          $(element).val(allBindings.value()).trigger('change');
        }
      }
      $(element).trigger("change");
    }
    };

function BookPossessionTransferVM() {
    var self = this;

    self.AllFromList = ([{"IsAdult":false,"Name":"Bob","ID":38438}, {"IsAdult":false,"Name":"Gordon","ID":54686}, {"IsAdult":true,"Name":"Bill","ID":45645}, {"IsAdult":false,"Name":"Sue","ID":1231}, {"IsAdult":false,"Name":"Ling","ID":123578}, {"IsAdult":false,"Name":"Ivy","ID":78945}]);
    self.AllToList = ([{"IsAdult":false,"Name":"Adam","ID":38438}, {"IsAdult":false,"Name":"Geoff","ID":54686}, {"IsAdult":true,"Name":"Josh","ID":45645}, {"IsAdult":false,"Name":"Sam","ID":1231}, {"IsAdult":false,"Name":"Ming","ID":123578}, {"IsAdult":false,"Name":"Austin","ID":78945}, {"IsAdult":false,"Name":"Tsz","ID":78945}, {"IsAdult":true,"Name":"Ireylnn","ID":78945}, {"IsAdult":true,"Name":"Isabelle","ID":78945},{"IsAdult":true,"Name":"Vickey","ID":78945}]);

    self.PossessionChanges  = ko.observableArray([]);
    self.PossessionChanges.push(new PossessionChangeVM(self.PossessionChanges().length +1));

      self.GetPersonById = function (id) {
      return ko.utils.arrayFirst(self.AllFromList, function (person) {
          return person.ID === ko.unwrap(id);
        });
    }

 self.AvailableFrom = ko.computed(function() {
    var available = ko.utils.arrayFilter(self.AllFromList, function(item) {
      return !ko.utils.arrayFirst(self.PossessionChanges() , function (possessionChange) {
         var person = self.GetPersonById(possessionChange.SelectedFrom());
         if (person) {
          return person.ID === item.ID;
         } else {
           return false;
         }
      });
    });
    return available;
  });

    self.AvailableTo = ko.computed(function() {
    var available = ko.utils.arrayFilter(self.AllToList, function(item) {
      return !ko.utils.arrayFirst(self.PossessionChanges() , function (possessionChange) {
         var person = self.GetPersonById(possessionChange.SelectedTo());
         if (person) {
          return person.ID === item.ID;
         } else {
           return false;
         }
      });
    });
    return available;
  });

    self.addPossessionChange = function () {
      self.PossessionChanges.push(new PossessionChangeModel(self.PossessionChanges().length + 1));
    }

    self.removePossessionChangeChange = function(possessionChange) {
      self.PossessionChanges.remove(possessionChange);
    }
  }

  function PossessionChangeVM(possessionChangeId) {
    var self = this;

        self.possessionChangeId = ko.observable(possessionChangeId);
    self.SelectedFrom = ko.observable();
    self.SelectedTo = ko.observable();

    self.ChangeType = ko.pureComputed(function() {
      if (self.SelectedFrom() !== undefined && self.SelectedTo() !== undefined) {
        return 'Update';
      } else if (self.SelectedFrom() === undefined && self.SelectedTo() === undefined) {
          return '';
      } else if (self.SelectedFrom() === undefined) {
        return 'Add';
      } else if (self.SelectedTo() === undefined) {
        return 'Remove';
      } else { return ''; }
    });
  }

  function SelectedPerson(isAdult, name, id) {
    var self = this;

    self.IsAdult  = ko.observable(isAdult);
    self.Name = ko.observable(name);
    self.ID = ko.observable(id);
  }

  ko.applyBindings(new BookPossessionTransferVM());

这也是jsfiddle:https ://jsfiddle.net/cpd5w9he/11/如果将person.ID更改为person,它可以工作,但是选项不正确

杰森·斯帕克(Jason Spake)

原始问题:从下拉列表中选择一项时,“ SelectedTo”的值会正确更改为该项的ID值。但是,然后重新计算下拉选项,然后从选项列表中删除该项目,从而使“ SelectedTo”的值恢复为未定义。您不能拥有不属于选项列表的选定值。

解决方案:以下代码片段可以满足您的需求。我不得不将根对象传递给PossessionChangeVM,我并不完全满意,但是它可以工作。这样,每个ownerChangeVM都使用FullList构建其自己的可用选项列表,并且仅在使用了该项目但不是当前项目的选定项目时进行过滤。

ko.bindingHandlers.select2 = {
    init: function (element, valueAccessor, allBindingsAccessor, bindingContext) {
      ko.utils.domNodeDisposal.addDisposeCallback(element,
        function() {
          $(element).select2('destroy');
        });
      var select2 = ko.utils.unwrapObservable(allBindingsAccessor().select2);
      $(element).select2(select2);
    },
    update: function (element, valueAccessor, allBindingsAccessor, bindingContext) {
      var allBindings = allBindingsAccessor();
      if ("value" in allBindings) {
        if ((allBindings.select2.multiple || element.multiple) && allBindings.value().constructor != Array) {
          $(element).val(allBindings.value().split(',')).trigger('change');
        } else {
          $(element).val(allBindings.value()).trigger('change');
        }
      }
      $(element).trigger("change");
    }
    };

function BookPossessionTransferVM() {
    var self = this;

    self.AllFromList = ([{"IsAdult":false,"Name":"Bob","ID":38438}, {"IsAdult":false,"Name":"Gordon","ID":54686}, {"IsAdult":true,"Name":"Bill","ID":45645}, {"IsAdult":false,"Name":"Sue","ID":1231}, {"IsAdult":false,"Name":"Ling","ID":123578}, {"IsAdult":false,"Name":"Ivy","ID":78945}]);
    self.AllToList = ([{"IsAdult":false,"Name":"Adam","ID":38438}, {"IsAdult":false,"Name":"Geoff","ID":54686}, {"IsAdult":true,"Name":"Josh","ID":45645}, {"IsAdult":false,"Name":"Sam","ID":1231}, {"IsAdult":false,"Name":"Ming","ID":123578}, {"IsAdult":false,"Name":"Austin","ID":78945}, {"IsAdult":false,"Name":"Tsz","ID":78945}, {"IsAdult":true,"Name":"Ireylnn","ID":78945}, {"IsAdult":true,"Name":"Isabelle","ID":78945},{"IsAdult":true,"Name":"Vickey","ID":78945}]);

  self.PossessionChanges  = ko.observableArray([]);
  
		self.UsedTo = ko.computed(function(){
    	return self.PossessionChanges()
        .filter(function(item){
          return item.SelectedTo() != undefined;
        })
        .map(function(item){
          return item.SelectedTo();
        });
    });
    self.UsedFrom = ko.computed(function(){
    	return self.PossessionChanges()
        .filter(function(item){
          return item.SelectedFrom() != undefined;
        })
        .map(function(item){
          return item.SelectedFrom();
        });
    });

    self.PossessionChanges.push(new PossessionChangeVM(self.PossessionChanges().length +1, self));
    
      self.GetPersonById = function (id) {
      return ko.utils.arrayFirst(self.AllFromList, function (person) {
          return person.ID === ko.unwrap(id);
        });
    }

    self.addPossessionChange = function () {
      self.PossessionChanges.push(new PossessionChangeVM(self.PossessionChanges().length + 1, self));
    }

    self.removePossessionChangeChange = function(possessionChange) {
      self.PossessionChanges.remove(possessionChange);
    }
  }

  function PossessionChangeVM(possessionChangeId, root) {
    var self = this;

		self.possessionChangeId = ko.observable(possessionChangeId);
    self.SelectedFrom = ko.observable();
    self.SelectedTo = ko.observable();
  
    
    self.AvailableFrom = ko.computed(function() {
      return ko.utils.arrayFilter(root.AllFromList, function(item) {
        return root.UsedFrom().indexOf(item.ID) < 0 || item.ID === self.SelectedFrom();
      });
  	});
    
    self.AvailableTo = ko.computed(function() {
      return ko.utils.arrayFilter(root.AllToList, function(item) {
        return root.UsedTo().indexOf(item.ID) < 0 || item.ID === self.SelectedTo();
      });
  	});

    self.ChangeType = ko.pureComputed(function() {
      if (self.SelectedFrom() !== undefined && self.SelectedTo() !== undefined) {
        return 'Update';
      } else if (self.SelectedFrom() === undefined && self.SelectedTo() === undefined) {
          return '';
      } else if (self.SelectedFrom() === undefined) {
        return 'Add';
      } else if (self.SelectedTo() === undefined) {
        return 'Remove';
      } else { return ''; }
    });
  }

  function SelectedPerson(isAdult, name, id) {
    var self = this;

    self.IsAdult  = ko.observable(isAdult);
    self.Name = ko.observable(name);
    self.ID = ko.observable(id);
  }
  
  ko.applyBindings(new BookPossessionTransferVM());
#tblPossessionChanges {
    width: 70%;
    height: 100px;
    text-align: center;
    table-layout: fixed;
  }

  #tblPossessionChanges td, #tblPossessionChanges th {
    padding: 1rem;
  }

  #tblPossessionChanges thead th {
    text-align: center;
  }

  #tblPossessionChanges thead th:first-child {
    text-align: left;
    width: 10%;
  }

  #tblPossessionChanges tbody td:first-child {
    text-align: left;
    width: 10%;
  }

  #tblPossessionChanges > tbody > tr > td.prompt > a{
    font-weight: bold;
  }

  #tblPossessionChanges tbody td select{
    width: 75%
  }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.12/js/select2.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet" />

<div>
  <table id="tblPossessionChanges">
    <thead>
      <tr>
        <th><a href="#" class="buttonSmall" data-bind="click: addPossessionChange">Add</a></th>
        <th>From</th>
        <th>To</th>
      </tr>
    </thead>
    <tbody data-bind="foreach: PossessionChanges">
      <tr>
        <td class="prompt">
          <a href="#" class="buttonSmall" data-bind="click: $root.removePossessionChange">Delete</a>           </td>
        <td>
          <select class="form-control" 
                  data-bind="options: AvailableFrom, 
                             value: SelectedFrom,
                             optionsText: function(i) {return i.Name}, 
                             optionsValue: function(i) {return i.ID},
                             optionsCaption: 'Please select a Person...',
                             select2: { placeholder: 'Please select a Person...', allowClear: false}">             </select>
        </td>
        <td>
          <select class="form-control"
                  data-bind="options: AvailableTo, 
                             value: SelectedTo, 
                             optionsText: function(i) {return i.Name}, 
                             optionsValue: function(i) {return i.ID},
                             optionsCaption: 'Please select a Person...',
                             select2: {placeholder: 'Please select a Person...', allowClear: false}">            </select>
        </td>
        <td>
          <span id="changeTypeSpan" data-bind="text: ChangeType"></span>
        </td>
      </tr>
    </tbody>
  </table>
  <br/>

</div>

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Knockout ValidationMessage 绑定不显示消息

Knockout.js多个下拉列表。

使用Knockout显示JSON响应的内容

在 Knockout-bound 下拉列表中显示值而不是文本

使用Struts标记在UI中无法正确显示Select2下拉列表

使用jQuery更新Knockout.js下拉列表和Knockout值

在Knockout的afterAdd回调中包含fadeIn()

选择元素未使用 Knockout 正确更新

使用Knockout JS动态显示/隐藏

Knockout JS中带有下拉列表的数组

jQuery mobile 1.4 select的Knockout.js 3.3.0选项绑定

Knockout/Select2:让下拉菜单在图书传输应用程序中正常工作的问题

如何使用Knockout.Js显示过滤列表的结果?

从select2下拉列表中选择某个选项后触发动作

在select2下拉列表中预填充选定的选项

如何使用从Select2下拉列表中选择的选项来触发jQuery?

使用Ajax时清除select2下拉列表的正确方法是什么?

Knockout.js hasfocus实现在动态添加的行上

以为我了解 Knockout.js,现在我不太确定

Knockout.js:合并javascript对象并选择选项

动态更改选项文本-knockout.js

嵌套值上的Knockout.js映射选项被忽略

使用Knockout填充列表时,使用AngularJs过滤列表

在Knockout数据绑定文本中包含span元素

Knockout JS:具有动态内容的动态标签

Knockout JS如何知道要传递的正确参数?

Knockout.js ul li 数据绑定不正确

将正确/错误绑定到Knockout JS中的单选按钮

Knockout.js CSS绑定的正确语法是什么?