2012-10-12 21 views
11

Ich versuche, herauszufinden, ob Knockout js gut für das folgende Problem funktionieren würde:Mit Knockout js mit jQuery UI Slider

ich mehrere Schieber, die ich auf Textfelder verknüpfen möchten.

Wenn das Textfeld geändert wird, muss der entsprechende Schieberegler auf den neuen Wert aktualisiert werden und umgekehrt.

Beim Ändern des Schiebereglers oder Textfelds muss eine Funktion aufgerufen werden, die die Eingabe aus allen Textfeldern verwendet, um ein Ergebnis zu berechnen.

Ich habe meine schnelle und schmutzige jQuery-Lösung here.

Wäre es einfacher, mit knockout js dasselbe Ergebnis eleganter zu erreichen?

Ich glaube, ich müsste eine benutzerdefinierte Bindung Handler wie sein in jQuery UI datepicker change event not caught by KnockoutJS

+0

Sie könnten diese Bibliothek verwenden: http://gvas.github.io/knockout-jqueryui/slider.html –

Antwort

36

hier getan zu schaffen, ist ein Beispiel: http://jsfiddle.net/jearles/Dt7Ka/

ich eine benutzerdefinierte Bindung verwenden, um die jquery-ui Schieber zu integrieren und verwenden Knockout Erfassen Sie die Eingaben und berechnen Sie den Nettobetrag.

-

UI

<h2>Slider Demo</h2> 

Savings: <input data-bind="value: savings, valueUpdate: 'afterkeydown'" /> 
<div style="margin: 10px" data-bind="slider: savings, sliderOptions: {min: 0, max: 100, range: 'min', step: 1}"></div> 

Spent: <input data-bind="value: spent, valueUpdate: 'afterkeydown'" /> 
<div style="margin: 10px" data-bind="slider: spent, sliderOptions: {min: 0, max: 100, range: 'min', step: 1}"></div> 

Net: <span data-bind="text: net"></span> 

Ansicht Modell

ko.bindingHandlers.slider = { 
    init: function (element, valueAccessor, allBindingsAccessor) { 
    var options = allBindingsAccessor().sliderOptions || {}; 
    $(element).slider(options); 
    ko.utils.registerEventHandler(element, "slidechange", function (event, ui) { 
     var observable = valueAccessor(); 
     observable(ui.value); 
    }); 
    ko.utils.domNodeDisposal.addDisposeCallback(element, function() { 
     $(element).slider("destroy"); 
    }); 
    ko.utils.registerEventHandler(element, "slide", function (event, ui) { 
     var observable = valueAccessor(); 
     observable(ui.value); 
    }); 
    }, 
    update: function (element, valueAccessor) { 
    var value = ko.utils.unwrapObservable(valueAccessor()); 
    if (isNaN(value)) value = 0; 
    $(element).slider("value", value); 
    } 
}; 

var ViewModel = function() { 
    var self = this; 

    self.savings = ko.observable(10); 
    self.spent = ko.observable(5); 
    self.net = ko.computed(function() { 
     return self.savings() - self.spent(); 
    }); 
} 

ko.applyBindings(new ViewModel()); 
+1

Vielen Dank! Viel eleganter als meine jQuery sln – woggles

+0

Ich sehe, dass es auch die Eingabe der Textfelder auf den Bereich der Schieberegler begrenzt ... genial :) Gibt es eine Möglichkeit, Benutzer zu verhindern, alles außer Zahlen einzugeben? Wenn ein Zeichen gesetzt wird, gibt es NaN – woggles

+0

aus Ich habe meinen Code oben und die Geige aktualisiert, um vor der Aktualisierung nach numerischen Werten zu suchen. Wenn NaN es setzt den Wert auf 0. –

9

Ich weiß, es vor ein paar Tagen, aber ich habe ein paar Anpassungen an John Earles Code:

ko.bindingHandlers.slider = { 
init: function (element, valueAccessor, allBindingsAccessor) { 
    var options = allBindingsAccessor().sliderOptions || {}; 
    $(element).slider(options); 
    ko.utils.registerEventHandler(element, "slidechange", function (event, ui) { 
     var observable = valueAccessor(); 
     observable(ui.value); 
    }); 
    ko.utils.domNodeDisposal.addDisposeCallback(element, function() { 
     $(element).slider("destroy"); 
    }); 
    ko.utils.registerEventHandler(element, "slide", function (event, ui) { 
     var observable = valueAccessor(); 
     observable(ui.value); 
    }); 
}, 
update: function (element, valueAccessor, allBindingsAccessor) { 
    var value = ko.utils.unwrapObservable(valueAccessor()); 
    if (isNaN(value)) value = 0; 
    $(element).slider("option", allBindingsAccessor().sliderOptions); 
    $(element).slider("value", value); 
} 
}; 

Der Grund für thi Wenn Sie Optionen verwenden, die sich ändern (z. B. eine andere beobachtbare Option), hat dies keine Auswirkungen auf den Schieberegler, auch wenn Sie dies wünschen.

2

@John Earles und @Michael Kire Hansen: Vielen Dank für Ihre wundervollen Lösungen!

Ich benutzte den erweiterten Code von Michael Kire Hansen. Ich habe die Option "max:" des Schiebereglers an eine ko.observable gebunden und es stellte sich heraus, dass der Schieberegler den Wert in diesem Fall nicht korrekt aktualisiert. Beispiel: Nehmen wir an, der Schieberegler ist auf dem Wert 25 von max 25 und Sie ändern den maximalen Wert auf 100, der Schieberegler bleibt an der richtigen Position, was bedeutet, dass er den maximalen Wert hat (aber der Wert ist immer noch 25, nicht 100). im „update:“ Teil wechseln nur die letzten beiden Zeilen: Sobald Sie einen Punkt nach links schieben, können Sie den Wert auf 99.

Lösung erhalten aktualisiert

$(element).slider("option", allBindingsAccessor().sliderOptions); 
$(element).slider("value", value); 

Dies ändert die Optionen zuerst, dann der Wert und es funktioniert wie ein Charme.

+0

Ich habe meine Antwort mit diesem Fix aktualisiert, danke :) –

0

Vielen Dank für die Hilfe, die ich brauchte eine Reihe Schieber in meinem Szenario verwenden hier so ist eine Erweiterung @John Earles und @ Michael Kire Hansen

ko.bindingHandlers.sliderRange = { 
init: function (element, valueAccessor, allBindingsAccessor) { 
    var options = allBindingsAccessor().sliderOptions || {}; 
    $(element).slider(options); 
    ko.utils.registerEventHandler(element, "slidechange", function (event, ui) { 
     var observable = valueAccessor(); 
     observable.Min(ui.values[0]); 
     observable.Max(ui.values[1]); 
    }); 
    ko.utils.domNodeDisposal.addDisposeCallback(element, function() { 
     $(element).slider("destroy"); 
    }); 
    ko.utils.registerEventHandler(element, "slide", function (event, ui) { 
     var observable = valueAccessor(); 
     observable.Min(ui.values[0]); 
     observable.Max(ui.values[1]); 
    }); 
}, 
update: function (element, valueAccessor, allBindingsAccessor) { 
    var value = ko.utils.unwrapObservable(valueAccessor()); 
    if (isNaN(value.Min())) value.Min(0); 
    if (isNaN(value.Max())) value.Max(0); 

    $(element).slider("option", allBindingsAccessor().sliderOptions); 
    $(element).slider("values", 0, value.Min()); 
    $(element).slider("values", 1, value.Max()); 
} 
}; 

und dann die HTML zu begleiten

<div id="slider-range" 
      data-bind="sliderRange: { Min: 0, Max: 100 }, 
           sliderOptions: { 
            range: true, 
            min: 0, 
            max: 100, 
            step: 10, 
            values: [0, 100] 
           }"></div>