2012-02-10 3 views
6

У меня есть группа флажковкак реализовать зависимости флажка в knockoutjs

  • флажок
  • Флажка Б
  • Флажок С

Сгенерированного с привязкой данных Foreach:

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

проверенное состояние из наблюдаемого массива. Таким образом, при проверке поля добавляется соответствующее значение массиву, стандартный класс knockoutjs, который отлично работает. Затем я хотел добавить простое правило: 0 C

Если проверка C, то необходимо также проверить A и B.

Каков самый чистый способ добавить эту логику в нокаут? Я попытался с записываемой вычислимая наблюдаемом:

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, чтобы избежать обработчик события, который будет прикреплен значением связывания, поскольку привязка значения предназначена для обработки изменений в поле. В этом случае мы хотим только установить атрибут value.

Образец здесь: http://jsfiddle.net/rniemeyer/tQJMg/

+0

Работает отлично, спасибо! (скрипка дает 404, хотя) – dgorissen

+0

Также следует добавить к этому, что для правильного использования тега

+1

Почему «shouldBeDisabled» вызывается для каждого элемента массива элементов? Я понимаю, почему он вызывается при изменении 'self.checked', но почему он перебирает весь массив' items'? – arb

 Смежные вопросы

  • Нет связанных вопросов^_^