Custom Knockout Binding Fires Twice, Unexpectedly
Solution 1:
I'm not sure this will help you, as nemesv answers in the comments above seem to be very close to what you wanted to achieve, ie. stopping the double update.
However, I've spent a bit of time on it, so I'll show you what I came up with anyway and hope it helps.
I didn't know about the peek() method that nemesv mentioned (great tip), so I looked into why it was updating twice based on the computeds etc.
I saw that your self.breakdownChart was accessing the currentScenario observable, and when I removed that as a test, the second update didn't occur.
So that got me thinking, why you needed that in there for the x axis setting.
So I added a new property to your scenario to return the current scenario name
self.name='Scenario' + self.number;
And then for the base scenario, changed this to "Base Scenario" to ensure that title appears correctly for just that series.
To ensure the legend/axis is correct, I added a new property to the chart object called baseSeriesName
self.breakdownChart = ko.computed(function(){
return {
baseSeriesTitle: baseScenario.name,
and that is set to the baseScenario's name.
Finally, to tie that all together in the BindingHandler, I update the xAxis in there:
//set the xAxis titles, only add the second title if different from the base
valueUnwrapped.xAxis={
categories: [valueUnwrapped.baseSeriesTitle, valueUnwrapped.baseSeriesTitle!=seriesUnwrapped[0].name ? seriesUnwrapped[0].name:'']
}
It's a bit of refactoring, but it achieves your goal; hope it helps.
Oh, I also added a chartType observable to the view model, and used that in the chart definition (breakdownChart computed), to test the double update wouldn't happen if the chart refreshed on a different observable and that it still initialised correctly - so the fiddle shows the chartType updating, without a double update.
Solution 2:
You get two updates because Knockout updates computed observables immediately when their dependencies change, and your binding has two dependencies, each of which gets updated in turn.
One way to solve this is to use a technique to delay updates of the binding. An easy way to do so is to use the Deferred Updates plugin, as demonstrated here: http://jsfiddle.net/mbest/8j6e5/15/
Deferred Updates uses setTimeout
to perform updates, which means that the update happens asynchronously. If you want it to be synchronous for a specific update, you can use ko.tasks.processImmediate
:
ko.tasks.processImmediate(function() {
self.scenarios.push(newScenario);
self.currentScenario(newScenario);
});
Post a Comment for "Custom Knockout Binding Fires Twice, Unexpectedly"