2012-02-10 26 views
6

Tôi có một nhóm các hộp kiểmlàm thế nào để thực hiện phụ thuộc hộp kiểm trong knockoutjs

  • checkbox Một
  • checkbox B
  • hộp kiểm C

tạo với các dữ liệu foreach ràng buộc:

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

Điều gì sẽ xảy ra kiểm tra nhà nước từ một observableArray. Vì vậy, việc kiểm tra một hộp sẽ thêm giá trị tương ứng vào mảng, tiêu chuẩn knockoutjs hoạt động tốt. Sau đó tôi muốn thêm một quy tắc đơn giản:

nếu chọn C, thì A và B cũng phải được kiểm tra.

Cách sạch nhất để thêm loại logic này vào knockoutj là gì? Tôi đã thử với một ghi tính toán quan sát:

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 
    }); 

Đưa một breakpoint vào đọc và viết các chức năng: đọc được gọi và tải trang tốt. Tuy nhiên, khi tôi sau đó nhấp vào bất kỳ hộp kiểm Tôi nhận được lỗi sau (write breakpoint không bao giờ bị đánh):

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' 

Trả lời

9

Khi checked ràng buộc là ràng buộc chống lại một mảng, sau đó nó cần để có thể thực hiện các thao mảng chống lại nó. Vì vậy, bằng cách sử dụng một khả năng ghi có thể ghi được trong trường hợp đó sẽ gây ra một vấn đề.

Tuy nhiên, bạn có thể chọn sử dụng đăng ký thủ công để giữ cho các mục của bạn được đồng bộ hóa.

Dưới đây là một cái nhìn mô hình mẫu:

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;  
    }; 
}; 

Dưới đây là quan điểm:

<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> 

tôi đã sử dụng attr: { value: id } thay vì value để tránh xử lý sự kiện đó sẽ được gắn bởi các ràng buộc giá trị, như ràng buộc giá trị được thiết kế để xử lý các thay đổi cho một trường. Trong trường hợp này, chúng tôi chỉ muốn đặt thuộc tính giá trị.

Mẫu tại đây: http://jsfiddle.net/rniemeyer/tQJMg/

+0

Hoạt động hoàn hảo, cảm ơn! (fiddle cung cấp cho một 404 mặc dù) – dgorissen

+0

Cũng nên có thể thêm vào điều này mà để có được một thẻ

+1

Tại sao 'shouldBeDisabled' được gọi cho mỗi mục trong mảng mục? Tôi hiểu tại sao nó được gọi khi thay đổi 'self.checked', nhưng tại sao nó lặp lại toàn bộ mảng' items'? – arb

Các vấn đề liên quan