2012-10-12 137 views
11

que estoy tratando de averiguar si knockout js funcionarían bien para el siguiente problema:Uso knockout js con deslizadores jquery ui

tengo varios controles deslizantes que quiero enlazar a cuadros de texto.

Cuando se cambia el cuadro de texto, el control deslizante correspondiente debe actualizarse al nuevo valor y viceversa.

Al cambiar el valor del control deslizante o el cuadro de texto, se debe invocar una función que utiliza la entrada de todos los cuadros de texto para calcular un resultado.

Tengo mi solución jQuery rápida y sucia here.

¿Sería fácil lograr el mismo resultado de una manera más elegante con knockout js?

supongo que tendría que crear un controlador de enlace personalizado al igual que su hecho en jQuery UI datepicker change event not caught by KnockoutJS

+0

Puede utilizar esta biblioteca: http://gvas.github.io/knockout-jqueryui/slider.html –

Respuesta

36

Aquí se muestra un ejemplo: http://jsfiddle.net/jearles/Dt7Ka/

utilizo una unión a medida para integrar el control deslizante jQuery-UI y utilizar Knockout a captura las entradas y calcula la cantidad neta.

-

IU

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

Ver Modelo

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

¡Gracias! Mucho más elegante que mi jQuery sln – woggles

+0

Veo que también limita la entrada de los cuadros de texto al rango de los controles deslizantes ... impresionante :) ¿Hay alguna manera de evitar que los usuarios ingresen nada más que números? Cuando un personaje lo pone, emite NaN – woggles

+0

. He actualizado mi código anterior y el violín para verificar el número antes de actualizar. Si NaN restablece el valor a 0. –

9

Sé que es hace unos días, pero he hecho algunos ajustes en el código John Earles:

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

La razón de thi s es que si usa opciones que cambian (fx otro observable) entonces no afectará el control deslizante incluso si usted quisiera que lo haga.

2

@John Earles y @Michael Kire Hansen: gracias por sus maravillosas soluciones!

Utilicé el código avanzado de Michael Kire Hansen. Ate la opción "max:" del control deslizante a un ko.observable y resultó que el control deslizante no actualiza correctamente el valor en este caso. Ejemplo: Digamos que el control deslizante está en el valor 25 de máximo 25 y cambia el valor máximo a 100, el control deslizante permanece en la posición más correcta, indicando que está en el valor máximo (pero el valor sigue siendo 25, no 100). Tan pronto como se desliza un punto a la izquierda, se obtiene el valor informado a 99.

Solución: en la "actualización" parte acaba de cambiar las dos últimas líneas a:

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

Estos cambios las opciones primero, luego el valor y funciona como un amuleto.

+0

He actualizado mi respuesta con esta revisión, gracias :) –

0

Muchas gracias por la ayuda, que necesitaba usar un control deslizante rango en mi escenario así que aquí es una extensión a @ John Earles y Kire @ Michael 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()); 
} 
}; 

y luego el código HTML para acompañarlo

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