The scales/axes are updated
An error is thrown Uncaught TypeError: Cannot set property 'options' of undefined
I'm trying to have dynamic charts where configuration (not just data) is fed from an external source.
Using Developer tools with Firefox, clicking update on your example, I get
TypeError: t.scales[e.id] is undefined.
Somewhat browser specific error message. The cause though, appears to be that you are wiping out some of the internals of what chartjs setup during the initialization / creation of the original chart object. Add
console.log(JSON.stringify(chart.options.scales.yAxes));
to see what is already there before modifying the options. Way more than what you see in the creation options passed to the constructor. To do what you want, you need to merge your new settings. Not just overwrite with them.
Have a look at jQuery.extend(true, …) for one way to do this. Other implementations are around, including one in the internals of chartjs. Something like (with jQuery)
chart.options.scales.yAxes = $.extend({}, chart.options.scales.yAxes, {[{
id: 'y-axis-1',
position: 'right',
ticks: {
min: 0
}
}]};
will probably do what you want. For this case. More complex situations are going to need more involved manipulation, to explicitly remove pieces that are not wanted in the update.
In this case, directly adding the new values should work fine. But that needs to be things like
chart.options.scales.yAxes[0].id = 'y-axis-1';
etc.
For the general case, generate the chart with the minimal options, save the section that is to be manipulated, then use a deep merge.
chart.options.scales.yAxes = $.extend( {}, savedBaseYaxes, newYaxesOptions );
Make sure that the save is a deep copy too, and there is always going to be the risk that the externally supplied options are going to be invalid, or inconsistent with the previous state of the chart instance. chart.update is intended for relatively small changes. Normally chart.update would be called just after modifying the object. So the settings change would be inside your update function. That is really the only safe way, since other things can trigger an update as well. Like resizing the browser, which changes the chart dimensions.
@mMerlin is definitely on the right track with extending this rather than replacing the array. The items in this array are merged with the axis type defaults during initialization and replacing it means that that is lost.
However, simply changing the logic to push another object onto the array also doesn't work. The error that currently appears probably comes from https://github.com/chartjs/Chart.js/blob/master/src/core/core.controller.js#L53 because the updateConfig function is not currently designed to add or remove scales. I think with some modification it could easily work, but it would require changes elsewhere in update() to ensure that the necessary parts of buildScales() run.
As an aside, we want to get rid of the xAxes and yAxes arrays at the next major version and replace them with a map by axis ID. That will simplify a lot of the internal code and ensure that IDs are always present. It will also make updates like this a lot nicer to work with.
@etimberg any word on how far off this feature is?
Seems to work with 2.8: http://plnkr.co/edit/c7nl2G4Zy5IUtPQTTJpY?p=preview
In v3, we've moved from arrays to a map of <id: scaleOptions> and this works nicely in v3. http://plnkr.co/edit/QK8DNhNvGbokuNPk
Most helpful comment
Using Developer tools with Firefox, clicking update on your example, I get
Somewhat browser specific error message. The cause though, appears to be that you are wiping out some of the internals of what chartjs setup during the initialization / creation of the original chart object. Add
to see what is already there before modifying the options. Way more than what you see in the creation options passed to the constructor. To do what you want, you need to merge your new settings. Not just overwrite with them.
Have a look at
jQuery.extend(true, …)for one way to do this. Other implementations are around, including one in the internals of chartjs. Something like (with jQuery)will probably do what you want. For this case. More complex situations are going to need more involved manipulation, to explicitly remove pieces that are not wanted in the update.
In this case, directly adding the new values should work fine. But that needs to be things like
etc.
For the general case, generate the chart with the minimal options, save the section that is to be manipulated, then use a deep merge.
Make sure that the save is a deep copy too, and there is always going to be the risk that the externally supplied options are going to be invalid, or inconsistent with the previous state of the chart instance. chart.update is intended for relatively small changes. Normally chart.update would be called just after modifying the object. So the settings change would be inside your update function. That is really the only safe way, since other things can trigger an update as well. Like resizing the browser, which changes the chart dimensions.