带淘汰的jQueryUI Spinner小部件

如何在Knockout绑定输入中使用jQuery UI Spinner小部件?

       Remove   

最好的方法是创建custom binding以将spinner绑定到输入:

 ko.bindingHandlers.spinner = { init: function(element, valueAccessor, allBindingsAccessor) { //initialize spinner with some optional options var options = allBindingsAccessor().spinnerOptions || {}; $(element).spinner(options); //handle the field changing ko.utils.registerEventHandler(element, "spinchange", function () { var observable = valueAccessor(); observable($(element).spinner("value")); }); //handle disposal (if KO removes by the template binding) ko.utils.domNodeDisposal.addDisposeCallback(element, function() { $(element).spinner("destroy"); }); }, update: function(element, valueAccessor) { var value = ko.utils.unwrapObservable(valueAccessor()), current = $(element).spinner("value"); if (value !== current) { $(element).spinner("value", value); } } }; 

然后只使用它而不是value绑定:

  

这是工作小提琴: http : //jsfiddle.net/vyshniakov/SwKGb/

此页面上的答案是正确和有用的。 然而,我发现,当有人在字段中键入值时,我的行为会变得很糟糕。 每一次按键似乎都会引发“旋转停止”事件。 此外,按键是绕过字段格式和options.step。 幸运的是,我们可以检查传入的事件,看看实际发生了什么。 可能有更好的方法但我认为无论如何我都会分享。

 // Abstract to a function to allow for multiple binding types function createSpinner(defaultOptions) { return { init: function (element, valueAccessor, allBindingsAccessor) { var options = $.extend(true, {}, allBindingsAccessor().spinnerOptions, defaultOptions); var widget = $(element); var observable = valueAccessor(); widget.spinner(options); // handle field changes onblur [copies field -> model] ko.utils.registerEventHandler(element, "blur", function (event) { var inputValue = Number(widget.spinner("value")); var modelValue = observable(); if (inputValue !== modelValue) { // Set the widget (this forces formatting and rounding) - does not fire events widget.spinner("value", inputValue); // Read the value back out (saves us rounding) var numberValue = Number(widget.spinner("value")); // Set the observable observable(numberValue); } }); // handle other field changes ko.utils.registerEventHandler(element, "spinstop", function (event) { // jQuery.spinner spinstop is a bit overzealous with its spinstop event. if (event.keyCode !== undefined) { // If it has a keyCode someone is typing... so don't interfere } else if (event.originalEvent && event.originalEvent.type === "mouseup") { // This is an *actual* spinstop var numberValue = Number(widget.spinner("value")); observable(numberValue); } }); // handle disposal ko.utils.domNodeDisposal.addDisposeCallback(element, function () { widget.spinner("destroy"); }); }, update: function (element, valueAccessor) { // [copies model -> field] var widget = $(element); var observable = valueAccessor(); var inputValue = Number(widget.spinner("value")); var modelValue = observable(); if (inputValue !== modelValue) { widget.spinner("value", modelValue); } } }; } ko.bindingHandlers.moneyspin = createSpinner({ numberFormat: 'C0', culture: 'en-GB', min: 0, incremental: true }); ko.bindingHandlers.intspin = createSpinner({ numberFormat: 'n0', culture: 'en-GB' }); 

@Artem Vyshniakov的回答是正确的。 但是,如果您正在寻找IE polyfill而不是在支持它的浏览器中替换html5数字输入,请尝试以下方法:

  ko.bindingHandlers.spinner = { init: function (element, valueAccessor, allBindingsAccessor) { if (Modernizr.inputtypes.number) { ko.bindingHandlers.value.init.apply(null, arguments); } else { //initialize spinner with some optional options var options = allBindingsAccessor().spinnerOptions || {}; $(element).spinner(options); //handle the field changing $(element).on("spinstop", function () { var observable = valueAccessor(); observable($(element).spinner("value")); }); //handle disposal ko.utils.domNodeDisposal.addDisposeCallback(element, function () { $(element).off("spinstop"); $(element).spinner("destroy"); }); } }, update: function (element, valueAccessor, allBindingsAccessor) { if (Modernizr.inputtypes.number) { ko.bindingHandlers.value.update.apply(null, arguments); } else { var value = ko.utils.unwrapObservable(valueAccessor()); var disable = allBindingsAccessor().disable; if (typeof disable !== "undefined") { $(element).spinner((disable) ? "disable" : "enable"); } var current = $(element).spinner("value"); if (value !== current) { $(element).spinner("value", value); } } } }; function Order(name, price, vat, number) { var self = this; self.Name = ko.observable(name); self.Price = ko.observable(price); self.VAT = ko.observable(vat); self.Number = ko.observable(number); self.Final = ko.computed(function() { return (self.Price() + self.VAT()) * self.Number(); }); } function ViewModel() { var self = this; self.orders = ko.observableArray(); self.removeOrder = function(item) { self.orders.remove(item); }; self.save = function() { alert(ko.toJSON(self)); }; } var viewModel = new ViewModel(); viewModel.orders.push(new Order("Sugar", 100, 15, 3)); viewModel.orders.push(new Order("Salt", 200, 25, 4)); viewModel.orders.push(new Order("Milk", 200, 35, 1)); ko.applyBindings(viewModel); 

完整的小提琴: http : //jsfiddle.net/mberkom/pCJWc/