I am trying to meld knockout and noUiSlider with a custom binding. I have found similar code for the jQuery-UI slider and Knockout and used that as a basis.
If I use the sliderko custom binding below, the noUisliders do not update the observables. I get NaN, and nothing in the input fields.
If I use the slider custom binding below with noUiSlider events directly, then everything works. The slider custom binding doesn't perform well, probably due to tracking the noUiSlider update event. However, that's the only way I could figure out how to get the slider to continuously update the input fields.
I'd like to use Knockout's registerEventHandler, but I'm not sure how to get that to work.
// noUiSlider
ko.bindingHandlers.slider = {
init: function(element, valueAccessor, allBindingsAccessor) {
var options = allBindingsAccessor().sliderOptions || {};
noUiSlider.create(element, options);
// works with with noUiSlider but not with knockout event bindings
element.noUiSlider.on('set', function(values, handle) {
var observable = valueAccessor();
observable(values[handle]);
});
// works with with noUiSlider but not with knockout event bindings
element.noUiSlider.on('update', function(values, handle) {
var observable = valueAccessor();
observable(values[handle]);
});
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
element.noUiSlider.destroy();
});
},
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
element.noUiSlider.set(value);
}
};
// using knockout event handlers
ko.bindingHandlers.sliderko = {
init: function(element, valueAccessor, allBindingsAccessor) {
var options = allBindingsAccessor().sliderOptions || {};
noUiSlider.create(element, options);
ko.utils.registerEventHandler(element, 'set', function(values, handle) {
var observable = valueAccessor();
observable(values[handle]);
});
ko.utils.registerEventHandler(element, 'update', function(values, handle) {
var observable = valueAccessor();
observable(values[handle]);
});
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
element.noUiSlider.destroy();
});
},
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
element.noUiSlider.set(value);
}
};
// initialization for NoUiSlider - saves from adding stuff into page
var sillysv = {
start: [10],
step: 0.01,
range: {
'min': 0,
'max': 100
}
};
var sillysp = {
start: [5],
step: 0.01,
range: {
'min': 0,
'max': 100
}
};
var ViewModel = function() {
var self = this;
self.savings = ko.observable();
self.spent = ko.observable();
self.net = ko.computed(function() {
return self.savings() - self.spent();
});
};
ko.applyBindings(new ViewModel());
<link href="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/8.1.0/nouislider.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/8.1.0/nouislider.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<h2>Slider Demo</h2>
Savings:
<input data-bind="value: savings" />
<div style="margin: 10px" data-bind="slider: savings, sliderOptions: sillysv"></div>
Spent:
<input data-bind="value: spent" />
<div style="margin: 10px" data-bind="slider: spent, sliderOptions: sillysp"></div>
Net: <span data-bind="text: net"></span>