2013-04-21 97 views
1

我試圖實現以下建議,但每次值更新時都沒有觸發所需的響應。這可能是由於我是Knockout的新手而引起的。敲除 - 無法使用訂閱更新可觀察值(由於擴展驗證)

我有一個綁定到TextBoxFor的observable(金額)。

@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 }); 

** A「viewModel.Amount()」中的控制檯中輸入顯示值作爲是1000,但在屏幕上的值仍然示出了作爲輸入值。

任何幫助,感激地接受

約翰

+0

非常感謝您的回覆Joseph - 我已經看到您的JSFiddle正常工作。我嘗試過在我的解決方案中實現,雖然我可以看到coerceMin函數在頁面加載時運行,但當我更改文本框中的值時不會命中。除了你在下面添加的代碼外,是否還有其他要求執行此操作的密鑰(來自JSFiddle)? – JohnT 2013-04-22 16:15:45

+0

有一個鬼祟的線'ko.validation.registerExtenders();'我沒有把它放在實際的擴展片段中。你有沒有把這行加入你的代碼? – 2013-04-22 18:08:05

+0

你好。是的,我已經包含了registerExtender,並且coerceMin代碼在頁面加載時觸發,而不是在輸入值時觸發。謝謝 – JohnT 2013-04-22 21:10:48

回答

1

據我所知淘汰賽驗證不提供直接從規則定義訪問任何可觀察能力。如果可能的話,您可以在自定義驗證規則中強制使用該值。

我發現的最佳選擇是爲您要強制的每個規則創建自定義擴展程序。

下面是「最小」規則爲例強迫擴展:

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/

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); 

編輯

我也看着你在這裏使用的擴展。 您可以添加到您的擴展最小值,並傳遞它的觀察值的參數。 你必須寫明明在你擴展的方法寫一些代碼

類似:

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


    } 
... 
} 
+0

嗨SiMet,謝謝你的迴應。我有幾個其他問題..........在你的第一個例子中,使用計算而不是訂閱,你的值綁定到哪個值?例如。我試了_amount和金額但計算器沒有觸發。有沒有辦法實現特定於可觀察的擴展器解決方案?我是KO新手,但它看起來像ko.extenders.numeric會影響所有觀察對象?謝謝 – JohnT 2013-04-22 09:07:32