Knockout - 无法使用Subscribe更新Observable值(由于扩展验证)

时间:2013-04-21 16:17:11

标签: knockout.js knockout-2.0 knockout-validation

我尝试过实施以下建议,但每次更新值时似乎都没有触发所需的反应。这可能是因为我是Knockout的新手。

我有一个可观察的(Amount)绑定到TextBoxFor。

@Html.TextBoxFor(m => m.Amount, new { type = "number", data_bind = "value: Amount" })

当输入一个值时,需要对其进行验证以确保它不超过999999.除此之外,如果该值小于50,则需要将其设置为50。时间'金额'的变化。

var viewModel = {
    Amount: ko.observable().extend({numeric: 0, max: 999999})
};

我已经尝试过实施解决方案(在上一篇文章的答案中),但我无法使用这些解决方案。

我想出的最好的是创建如下计算。这将检查输入值并在第一次尝试时正确更新。后续的值更改不会触发屏幕上的更改,而是逐步执行代码,似乎更新了ViewModel.Amount值。

@Html.TextBoxFor(m => m.Amount, new { type = "number", data_bind = "value: amountMin" })


quoteVehicleViewModel.VehicleMileage = ko.observable(0);


viewModel.amountMin = ko.computed({
    read: function () {
        return viewModel.Amount();  
    },
    write: function (value) {
        if (value < 50) {
            viewModel.Amount(50);
        }
    }
}).extend({ numeric: 0, max: 999999 });

**在控制台中输入的“viewModel.Amount()”将值显示为1000,但屏幕上的值仍显示为输入的值。

感激地收到任何帮助

约翰

2 个答案:

答案 0 :(得分:1)

据我所知,敲除验证不提供直接从规则定义访问observable的任何能力。如果可能,您可以在自定义验证规则中强制执行该值。

我发现的最佳替代方法是为您要强制执行的每条规则创建自定义扩展程序。

以下是“min”规则的强制扩展示例:

  ko.extenders.coerceMin = function (target, enable) {
      //collect rule values
      var minRule = ko.utils.arrayFirst(target.rules(), function (val) {
          return val.rule === "min"
      });
      if (minRule === null) {
          throw Error("coerceMin extender must be used in conjunction with the 'min' knockout validation rule");
      }
      var minValue = minRule.params;
      //listen for changes and coerce when necessary
      var subscription = null;
      if (enable && !subscription) {
          subscription = target.subscribe(function (newValue) {
              if (!isNaN(newValue)) {
                  var newValueAsNum = parseFloat(+newValue);
                  var valueToWrite = newValueAsNum < minValue ? minValue : newValueAsNum;
                  //only write if it changed
                  if (valueToWrite !== newValue) {
                      target(valueToWrite);
                  }
              }
          });
      } else {
          if (subscription) {
              subscription.dispose();
          }
      }

      //return the original observable
      return target;
  };

您可以在视图模型中应用它,如下所示:

var viewModel = {
    Amount: ko.observable()
              .extend({numeric: 0, min: 50, max: 999999})
              .extend({coerceMin: true});
};

这是一个演示的小提琴:http://jsfiddle.net/f2rTR/1/

答案 1 :(得分:0)

非常相似的问题在这里: Make Knockout applyBindings to treat select options as number

尽管订阅,您仍可以计算出值。 它看起来像是:

var viewModel = {
    _amount: ko.observable(100).extend({numeric: 0, max: 999999, reset: true}),
    Amount : ko.computed(function(){
       return _amount < 50 ? 50 : _amount;
   })
};


ko.applyBindings(viewModel);

修改

我还看过你在这里使用的扩展器。 你可以添加你的扩展器最小值并传递你的observable的参数。 你必须在扩展程序的write方法中编写一些代码

类似的东西:

ko.extenders.numeric = function(target, min) {
...
   write:function(v){
      ...
      if(v<50) v=50;
      ...
      target(v)


   }
...
}