if绑定下的嵌套选项会导致错误的行为

时间:2018-02-15 22:29:12

标签: html knockout.js

我希望options不使用<option>绑定,并将if元素嵌套在if绑定下。

以下是我所做的(这里也是fiddle),它显示了我不期待的行为:var DogHouseViewModel = function() { var self = this; self.allowedNames = ["A", "B", "C"]; self.puppies = ko.observableArray([]); self.createPuppy = function () { self.puppies.push(new DogViewModel()); } self.isNameAlreadyTaken = function (puppyName) { var puppies = self.puppies(); for (var i = 0; i < puppies.length; i++) { if (puppies[i].dogName() == puppyName) { return true; } } return false; } self.printPuppiesName = function () { self.puppies().forEach(function (puppy) { alert(puppy.dogName()) }) } } var DogViewModel = function (dogName) { var self = this; self.dogName = ko.observable(); } vm = new DogHouseViewModel() ko.applyBindings(vm);似乎为每个选项选择触发,而我所期望的是,只有在将选项元素添加到DOM时它才会触发。

因此,当选择一个选项时,它不会显示。只有在再次选择相同选项时,它才会呈现应有的效果。

我做错了什么?

&#13;
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/2.1.0/knockout-min.js"></script>
<div>  
   <button data-bind="text: 'create a puppy', click: createPuppy"></button>
   <button data-bind="text: 'print puppies names', click: printPuppiesName"></button>
   <div data-bind="foreach: puppies">
      <select data-bind="value: dogName">
         <!-- ko foreach: $parent.allowedNames -->
            <!-- ko if: !($root.isNameAlreadyTaken($data)) -->
               <option data-bind="value: $data, text: $data"></option> 
            <!-- /ko -->
         <!-- /ko -->
      </select>
   </div>
</div>
&#13;
man bash | less +/'Here Strings' 
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

我相信这就是你想要做的。问题是你的allowedNames是选项的值,你可以从阵列中删除它们。但是你可以克隆父数组,并且当它更改计算数组时返回一个未使用的值列表。

我还添加了一张支票,以确保在没有名字的情况下我们不会意外地将小狗对象添加到小狗阵列。

&#13;
&#13;
var DogHouseViewModel = function() {
  var self = this;
  self.allowedNames = ["A", "B", "C"];
  self.puppies = ko.observableArray([]);

  self.createPuppy = function() {
    var newPuppy = new DogViewModel(self);
    if(newPuppy.allowedNames().length > 0) { // Check to see if there are any names left.   
      self.puppies.push(newPuppy);
    }
  }
  self.removePuppy = function(obj) {
    self.puppies.remove(obj);
  }

  self.printPuppiesName = function() {
    self.puppies().forEach(function(puppy) {
      alert(puppy.dogName())
    })
  }
}

var DogViewModel = function(parent) {
  var self = this;
  self.dogName = ko.observable();
  self.allowedNames = ko.computed(function() {
    var allowedNamesClone = parent.allowedNames.slice(0);
    var usedNames = parent.puppies().filter(function(pup) { // get all pups who have a name
      return pup.dogName() !== '' && pup.dogName() !== self.dogName();
    })
    usedNames.forEach(function(pup) {
      var index = allowedNamesClone.indexOf(pup.dogName());
      if (index > -1) {
        allowedNamesClone.splice(index, 1); // remove name from cloned array
      }
    })
    return allowedNamesClone; // return new array
  })
}

vm = new DogHouseViewModel()
ko.applyBindings(vm);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div>
  <button data-bind="text: 'create a puppy', click: createPuppy"></button>
  <button data-bind="text: 'print puppies names', click: printPuppiesName"></button>
  <div data-bind="foreach: puppies">
    <!-- ko if: allowedNames().length > 0 -->
    <select data-bind="options: allowedNames, value: dogName"></select>
    <button data-bind="click: $root.removePuppy">x</button>
    <!-- /ko -->
  </div>
</div>
&#13;
&#13;
&#13;