2012-10-17 31 views
10

Làm cách nào để sử dụng tiện ích jQuery UI Spinner trong đầu vào bị ràng buộc Knockout?Tiện ích jQueryUI Spinner với loại trực tiếp

<tbody data-bind="foreach: orders"> 
     <tr> 
      <td data-bind="text: Name"></td> 
      <td><input type="number" style="width: 100px;" data-bind="value: Price" /></td> 
      <td><input type="number" style="width: 50px;" data-bind="value: VAT" /></td> 
      <td><input type="number" style="width: 50px;" data-bind="value: Number" /></td> 
      <td data-bind="text: Final()"></td> 
      <td><a href="javascript:void(0);" data-bind="click: $root.removeOrder">Remove</a></td> 
     </tr>  
    </tbody> 
+0

Trường nào bạn muốn áp dụng bộ xoay tròn? –

Trả lời

19

Cách tốt nhất là để tạo ra custom binding để ràng buộc spinner vào đầu vào:

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

Và sau đó chỉ cần sử dụng nó thay vì value ràng buộc:

<input 
    type="number" 
    style="width: 100px;" 
    data-bind="spinner: Price, spinnerOptions: { min: 0 } " /> 

Dưới đây là fiddle làm việc: http://jsfiddle.net/vyshniakov/SwKGb/

+0

Wow. Cảm ơn bạn rất nhiều –

+0

@Artem - mã tuyệt vời! Bất kỳ cách nào để làm cho nó cháy w/mỗi nhấp chuột? Không chỉ khi tập trung lá? – ajwaka

+2

@Artem - tìm thấy "một phần" nó - thay đổi "spinchange" thành "spinstop" - không hoạt động trong Chrome – ajwaka

0

@Artem Vyshni Câu trả lời của akov là đúng. Tuy nhiên, nếu bạn đang tìm kiếm một polyfill IE thay vì thay thế số lượng đầu vào html5 trong các trình duyệt có hỗ trợ nó, hãy thử này:

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

Hoàn Fiddle ở đây: http://jsfiddle.net/mberkom/pCJWc/

2

Những câu trả lời trên trang này là chính xác và hữu ích. Tuy nhiên, tôi thấy rằng tôi đã nhận được hành vi xấu khi ai đó đang gõ một giá trị trong lĩnh vực này. Mỗi lần nhấn phím dường như cũng kích hoạt sự kiện "spinstop". Hơn nữa, các phím bấm đã bỏ qua định dạng trường và các tùy chọn. May mắn là chúng ta có thể kiểm tra sự kiện đến để xem điều gì đang xảy ra. Có thể có những cách tốt hơn nhưng tôi nghĩ tôi sẽ chia sẻ.

// 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' }); 
Các vấn đề liên quan