2012-02-10 44 views
6

我有一组复选框的在knockoutjs如何实现复选框依赖性

  • 复选框甲
  • 复选框乙
  • 复选框Ç

与在foreach数据绑定生成:

<input type="checkbox" data-bind="value: id, checked: $root.chkboxSelected" /> 

拿哪个从observableArray检查状态。因此,选中一个框会将相应的值添加到数组中,标准的knockoutjs工作正常。然后我想添加一个简单的规则:如果C被选中,那么A和B也必须被检查。

在knockoutjs中添加这种逻辑的最简单方法是什么?我试图用一个可写可计算观察到:

var viewModel = { 
     foo: observableArray(), 
     .. 
    }; 

viewModel.chkboxSelected = ko.computed({ 
     read: function() { 
     return this.foo(); 
     }, 
     write: function(value){ 
      //add it if not added already 
     if($.inArray(value, this.foo()) < 0) { 
      this.foo.push(value); 
     } 

      // if C is present then A,B must be as well   
     if($.inArray("C", this.foo()) >= 0) { 
      if($.inArray("B", this.foo()) < 0) { 
      this.foo().push("B"); 
      } 

      if($.inArray("A", this.foo()) < 0) { 
       this.foo().push("A"); 
      } 

     } 
     }, 
     owner: viewModel 
    }); 

把所读出的一个断点,写功能:读取被调用和页面加载罚款。然而,当我再单击任何复选框,我得到以下错误(写断点从未被击中):

knockout-2.0.0.debug.js:2297 

Uncaught TypeError: Object function dependentObservable() { 
     if (arguments.length > 0) { 
      if (typeof options["write"] === "function") { 
       // Writing a value 
       var valueForThis = options["owner"] || evaluatorFunctionTarget; // If undefined, it will default to "window" by convention. This might change in the future. 
       options["write"].apply(valueForThis, arguments); 
      } else { 
       throw "Cannot write a value to a dependentObservable unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters."; 
      } 
     } else { 
      // Reading the value 
      if (!_hasBeenEvaluated) 
       evaluateImmediate(); 
      ko.dependencyDetection.registerDependency(dependentObservable); 
      return _latestValue; 
     } 
    } has no method 'push' 

回答

9

checked被绑定针对一个数组,那么它需要能够执行数组操作对它。因此,在这种情况下使用可写的计算观察值将会导致一个问题。

但是,您可以选择使用手动订阅来保持项目同步。

下面是一个示例视图模型:

var ViewModel = function() { 
    var self = this; 
    this.items = ko.observableArray([ 
     { id: "A" }, 
     { id: "B" }, 
     { id: "C" }, 
     { id: "D" } 
     ]); 
    this.checked = ko.observableArray(); 
    this.checked.subscribe(function(newValue) { 
     if (self.checked.indexOf("C") > -1) { 
      if (self.checked.indexOf("A") < 0) { 
       self.checked.push("A"); 
      } 
      if (self.checked.indexOf("B") < 0) { 
       self.checked.push("B"); 
      } 
     } 
    }); 

    this.shouldBeDisabled = function(item) { 
     return (item.id === "B" || item.id ==="A") && self.checked.indexOf("C") > -1;  
    }; 
}; 

这里是视图:

<ul data-bind="foreach: items"> 
    <li> 
     <span data-bind="text: id"></span> 
     <input type="checkbox" data-bind="attr: { value: id }, checked: $root.checked, disable: $root.shouldBeDisabled($data)" /> 
    </li> 
</ul> 

我用attr: { value: id }代替value避免将由值绑定要连接的事件处理程序,因为值绑定旨在处理字段的更改。在这种情况下,我们只想设置值属性。

样品在这里:http://jsfiddle.net/rniemeyer/tQJMg/

+0

完美的作品,谢谢! (但小提琴404虽然) – dgorissen 2012-02-10 15:22:08

+0

也应该增加这个,为了让

+1

为什么'shouldBeDisabled'被调用项目数组中的每个项目?我明白为什么self.checked会被调用,但为什么它会遍历整个'items'数组呢? – arb 2012-05-31 17:47:15

相关问题