как реализовать флажок зависимости в knockoutjs - PullRequest
6 голосов
/ 10 февраля 2012

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

  • флажок A
  • флажок B
  • флажок C

Генерируется с данными 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'

1 Ответ

9 голосов
/ 10 февраля 2012

Когда привязка 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/

...