Knockout/Select2下拉列表包含正确的选项,但现在不显示任何内容 [英] Knockout/Select2 Dropdownlist contains correct options, but now displays nothing as selected

查看:81
本文介绍了Knockout/Select2下拉列表包含正确的选项,但现在不显示任何内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

So I have two dropdown lists that I'm using with knockout and select. When the availablePeople list returns all false (doesn't work properly), I am able to select and retain the person I chose. However, when the available people list works properly, I am not able to see the dropdown selection that I chose. To elaborate on the availablePeople List, if you select a person, that person can no longer be selected in future rows.

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,则可以,但是选项不正确

Here's the jsfiddle as well: https://jsfiddle.net/cpd5w9he/11/ If you change person.ID to person, it works, but the options are then incorrect

推荐答案

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

Original problem: When you select an item from the dropdown the value of "SelectedTo" correctly changes to that item's ID value. However, the dropdown options are then recomputed and that item is then removed from the list of options, causing the value of "SelectedTo" to revert back to undefined. You can't have a selected value that isn't part of the options list.

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

Solution: Here's a snippet that does what you want. I had to pass the root object down into the PossessionChangeVM which I'm not totally happy with, but it works. This way each possessionChangeVM builds its own list of available options using the FullList, and filtering only when the item has been used but is not the current item's selected one.

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>

这篇关于Knockout/Select2下拉列表包含正确的选项,但现在不显示任何内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆