2012-10-17 7 views
10

Knockoutバインド入力でjQuery UI Spinnerウィジェットを使用するにはどうすればよいですか?ノックアウトのjQueryUI Spinnerウィジェット

<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

どのフィールドにスピナーを適用しますか? –

答えて

19

最良の方法は、入力にspinnerバインドするcustom bindingを作成することです:

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の代わりにそれを使用します。ここでは

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

をフィドル取り組んでいます。 http://jsfiddle.net/vyshniakov/SwKGb/

+0

うわー。ありがとうございました –

+0

@Artem - 素晴らしいコード!それぞれのクリックで火をつける方法はありますか?フォーカスが去ったときだけでなく、 – ajwaka

+2

@Artem - 見つかりました "part" it - "spininst"を "spinstop"に変更 - Chromeで動作していません – ajwaka

0

@Artem Vyshni akovの答えは正しいです。しかし、あなたがIEのポリフィルを探しての代わりに、それをサポートするブラウザで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/

2

このページの答えが正しいされています役に立つと助かります。私は、誰かがフィールドに値を入力しているときに私が悪い動作をしていたことがわかりました。キーを押すたびに「spinstop」イベントが発生するようです。さらに、キーの押下は、フィールドの書式設定と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' }); 
関連する問題