使用计算

时间:2016-06-20 21:37:58

标签: javascript knockout.js

我们说我有类似<input type="text" data-bind="format: quantity">的内容,它使用名为bindingHandlers的自定义format定义如下:

var getElementValue = function($element) {
  return $element.val().replace(/\$/g, '');
};

ko.bindingHandlers.format = {
  init: function(element, bindingAccessor) {
    var $element = $(element),
      bindings = bindingAccessor();

    $element.val('$' + ko.unwrap(bindings));

    $element.change(function () {
      bindings(getElementValue($element));
    });
  },
  update: function(element, bindingAccessor) {
    var $element = $(element),
      bindings = bindingAccessor();
  $element.val('$' + ko.unwrap(bindings));
  }
};

和视图模型一样:

var ViewModel = function() {
  var self = this;
  self._quantity = ko.observable(0);
  self.quantity = ko.computed({
    read: self._quantity,
    write: function(newValue) {
      if (newValue < 0) {
        self._quantity.valueHasMutated();
        console.log('quantity is invalid');
        return;
      }
      self._quantity(newValue);
    }
    });
}

由于不允许负数,因此如果提供了输入,则可以将输入恢复为之前的值。

但是,self._quantity.valueHasMutated();函数中的write未通知bindingHandlers update突变。

有什么想法吗?我有JSFiddle setup for more details

2 个答案:

答案 0 :(得分:0)

我并不完全确定为什么你的代码无法正常工作,但我确实尝试了一些东西并想出了一些可以做到的事情......

由于您的输入已绑定到quantity,因此发送此值已更改的消息是有意义的。您可以通过在计算机上调用notifySubscribers来执行此操作:

self.quantity.notifySubscribers(self.quantity.peek());

这仍然感觉有点奇怪,我建议调查像these examples中那样的扩展器。

这是一个更新的小提琴:http://jsfiddle.net/pxxnuu2z/

答案 1 :(得分:0)

最简单的解决方案是通过对两者使用.extend({ notify: 'always' }),使用“备份”可观察对象来计算以反映更改时,告诉knockout对旧更改和新值的变化作出反应在文本输入中:

  self._quantity = ko.observable(0).extend({ notify: 'always' });
  self.quantity = ko.computed({
    read: self._quantity,
    write: function(newValue) {
      if (newValue < 0) {
        self._quantity(self._quantity.peek());
        //self._quantity.valueHasMutated();
        console.log('quantity is invalid');
        return;
      }
      self._quantity(newValue);
    }
  }).extend({ notify: 'always' });

小提琴:http://jsfiddle.net/k0deqt8x/

编辑:

BTW,此解决方案在使用ko.options.deferUpdates = true;

时也有效

或者,您可以使用更为标准的解决方案,例如rniemeyer在此创建的解决方案:http://www.knockmeout.net/2011/03/guard-your-model-accept-or-cancel-edits.html