Knockout.js 淘汰赛-Can';t使用Subscribe更新可观测值(由于扩展验证)

Knockout.js 淘汰赛-Can';t使用Subscribe更新可观测值(由于扩展验证),knockout.js,knockout-2.0,knockout-validation,Knockout.js,Knockout 2.0,Knockout Validation,我曾尝试实施下面的建议,但每次更新值时,这两个建议似乎都不会触发所需的反应。这可能是由于我的执行,因为我是新的击倒 我有一个可观察的(金额)绑定到TextBoxFor @Html.TextBoxFor(m => m.Amount, new { type = "number", data_bind = "value: Amount" }) 输入值时,需要对其进行验证,以确保其不超过999999。此外,如果该值小于50,则需要将其设置为50。每次“金额”发生变化时,都需要进行这些检查 var

我曾尝试实施下面的建议,但每次更新值时,这两个建议似乎都不会触发所需的反应。这可能是由于我的执行,因为我是新的击倒

我有一个可观察的(金额)绑定到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 });
@Html.TextBoxFor(m=>m.Amount,新的{type=“number”,data\u bind=“value:amountMin”})
QuoteVehiclevewModel.VehicleMileage=ko.可观察(0);
viewModel.amountMin=ko.computed({
读:函数(){
返回viewModel.Amount();
},
写入:函数(值){
如果(值<50){
viewModel.金额(50);
}
}
}).extend({数字:0,最大值:999999});
**控制台中输入的“viewModel.Amount()”显示值为1000,但屏幕上的值仍显示为输入的值

感激地接受任何帮助


约翰

非常相似的问题在这里:

您可以在不考虑订阅的情况下生成计算值。 它看起来像:

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);
var viewModel={
_金额:ko.observable(100).extend({numeric:0,max:999999,reset:true}),
金额:ko.computed(函数(){
退货金额<50?50:\金额;
})
};
应用绑定(视图模型);
编辑

我还研究了您在这里使用的扩展器。 您可以向extender min值中添加值,并将其传递给observable的参数。 显然,您必须在扩展器的write方法中编写一些代码

比如:

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


   }
...
}
ko.extenders.numeric=函数(目标,最小值){
...
写入:函数(v){
...

如果(v据我所知,敲除验证不提供任何直接从规则定义访问可观察对象的功能。如果可能,您可以在自定义验证规则中强制正确的值

我发现的最好的替代方法是为要强制的每个规则创建一个自定义扩展程序

下面是“min”规则的强制扩展程序示例:


这里有一个小提琴来演示:

你好,SiMet,谢谢你的回答。我还有几个问题…………在你的第一个示例中,使用computed而不是subscribe,你将你的值绑定到哪个值?例如,我尝试了_amount和amount,但没有触发computed。有没有办法实现Extender sol注意:这是特定于可观察对象的?我对KO不太熟悉,但它看起来像KO.extenders.numeric会影响所有可观察对象?感谢您的回复Joseph-我已经看到您的JSFIDLE正在工作。我已经尝试在我的解决方案中实现,虽然我可以看到在页面加载时运行强制函数,但当我在文本框。除了您在下面添加的代码之外,是否还需要其他键(来自您的JSFIDLE)来执行此操作?这里有一行狡猾的代码
ko.validation.registerExtenders()
我在回答中没有将其放入实际的扩展程序片段中。您的代码中包含这一行吗?您好。是的,我包含了registerExtenders,并且强制代码在页面加载时触发,而不是在输入值时触发。谢谢
  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});
};