Knockout在循环中嵌套绑定

时间:2016-10-03 16:22:12

标签: javascript jquery html knockout.js

我继续学习淘汰赛并继续面对我不知道如何克服的奇怪问题。

我有以下html页面和js脚本:

HTML:

<div data-bind="debug: $data, foreach: objects">
    <span hidden="hidden" data-bind="value: type.id"></span>
    <input type="text" data-bind="value: type.title" />
    <button type="button" data-bind="click: $parent.removeObject">- </button>
  </div>
  <div class="control-group form-inline">
    <select data-bind="options: availableTypes, optionsValue: function(item) {return item;},
                        optionsText: function(item) {return item.title;}, value: itemToAdd.type,
                        optionsCaption: 'Select types...'"></select>
    <button type="button" data-bind="click: addObject">+</button>
  </div>
</div>  

JS:

function model() {
  var self = this;

  var types = [new Type("1"), new Type("2"), new Type("3")];
  var objects = [new Object("1")];

  self.objects = ko.observableArray(objects);

  self.usedTypes = ko.computed(function() {
    return types.filter(function(type) {
      for (var j = 0; j < self.objects().length; j++) {
        if (self.objects()[j].type.id === type.id) {
          return true;
        }
      }
      return false;
    });
  }, self);

  self.availableTypes = ko.computed(function() {
    return types.filter(function(type) {
      for (var j = 0; j < self.usedTypes().length; j++) {
        if (self.usedTypes()[j].id === type.id) {
          return false;
        }
      }
      return true;
    });
  }, self);

  self.itemToAdd = new Object();

  self.addObject = function() {
    self.objects.push(self.itemToAdd);
    self.itemToAdd = new Object();
  };

  self.removeObject = function(object) {
    self.objects.remove(object);
  };
};

function Object(type) {
  var self = this;
  self.type = new Type(type);
}

function Type(id) {
  var self = this;
  self.id = id;
  self.title = id;
}
ko.applyBindings(new model());

我简化了模型以显示错误。问题是淘汰赛声称这样做是违法的:
<span hidden="hidden" data-bind="value: type.id"></span>
因为它无法在上下文中找到属性id。据我所知,它就在那里,一切都还可以。

请问,有人指出我的错误吗?

P.S。这是JsFiddle

ADDITION
感谢@Daryl的帮助,我能够将问题本地化。如果我更换

  self.itemToAdd = new Object();

  self.addObject = function() {
    self.objects.push(self.itemToAdd);
    self.itemToAdd = new Object();
  };

使用:

  self.itemToAdd = new Object();

  self.addObject = function() {
    self.objects.push(new Object(1));
    self.itemToAdd = new Object();
  };  
但是,以下代码仍然无效:

  self.itemToAdd = new Object("1");

  self.addObject = function() {
    self.objects.push(self.itemToAdd);
    self.itemToAdd = new Object();
  };  

似乎itemToAdd个对象被绑定到的html元素填充不正确。但我仍然不知道到底出了什么问题。

1 个答案:

答案 0 :(得分:0)

您已允许未设置类型下拉列表。当淘汰赛显示标题时,它会清除实际值。这意味着,通过呈现UI,您的itemToAdd.type将被清除。

您的第二种方法是通过不使用数据绑定实例来解决此问题。

此外:

  • 如果我是你,我不会覆盖Object构造函数...查找其他名称。
  • 如果要对UI进行双向绑定,请确保itemToAdd具有可观察的属性。