With the click of a button, I want to update a d3js plot based on the values of two select elements. If I understand it right, simply calling the valueAccessor
should fire off the update function, which is not happening in my code.
I have the following custom binding:
ko.bindingHandlers.plotSvg = {
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
valueAccessor();
console.log("Update d3js plot");
}
};
And the view:
<div class="panel-body">
<div class="row">
<div class="col-xs-2">
<select class="form-control"
data-bind="options: $root.options,
optionsText: 'name',
value: firstSelectedOption">
</select>
</div>
<div class="col-xs-2">
<select class="form-control"
data-bind="options: $root.options,
optionsText: 'name',
value: secondSelectedOption">
</select>
</div>
<div class="col-xs-2 col-xs-offset-5">
<button class="btn btn-primary" data-bind="click: updatePlot">
Visualise
</button>
</div>
</div>
<div data-bind="plotSvg: updatePlot"></div>
</div>
updatePlot
is a function in the viewmodel, and all it does is print a value at the moment.
edit The javascript: http://pastebin.com/2qKLf6yf The view: http://pastebin.com/TPvmKgxL
<div data-bind="plotSvg: updatePlot"></div>
needs to reference a computed, otherwise knockout won't know when the value of something has changed and thus will never fire the custom binding's update method.
I'd recommend something like:
<div data-bind="plotSvg: selectedValue"></div>
and
ko.bindingHandlers.plotSvg = {
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
viewModel.redrawPlot();
console.log("Update d3js plot");
}
};
where selectedValue
is a computed that tracks currently selected value on your form, and gets updated when the button is clicked.
Since you're using two values, you can do something like this in your viewModel to trigger an observable change:
this.selectedValue = ko.observable(null);
this.updatePlot = function(){
this.selectedValue(this.firstSelectedOption()+""+this.secondSelectedOption()+"")
}
Doing it this way will ensure its a unique string each time one of the options change. If neither change, then the observable won't change, and the plot shouldn't redraw. Its brute force, but it should work with what you have setup.