-
Notifications
You must be signed in to change notification settings - Fork 11.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix scale options update error #4198
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely needs tests before we could merge this
src/core/core.controller.js
Outdated
newOptions = helpers.configMerge( | ||
Chart.defaults.global, | ||
Chart.defaults[chart.config.type], | ||
newOptions || {}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this can just be newOptions
since it already had to have the scale
or scales
properties on line 47
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the advice, I will change this.
I can see it working fine by building the new bundle. Should I write a test case for this? Can you suggest a test file for me to add one, I'd love to contribute one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the best location for tests would be in https://github.com/chartjs/Chart.js/blob/master/test/specs/core.controller.tests.js 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually creating a new options object every update. A flag set by the setter of chart.options.scales
can be used to skip unnecessary change.
As the update
function isn't called frequently I guess it's ok to update every time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry for the delay in reviewing this. I added a question about what happens when axes are added or removed
src/core/core.controller.js
Outdated
if (newOptions.scale) { | ||
chart.scale.options = newOptions.scale; | ||
} else if (newOptions.scales) { | ||
newOptions.scales.xAxes.concat(newOptions.scales.yAxes).forEach(function(scaleOptions) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens in the case where new axes are added? I think we'd need to create those scale objects somewhere in here. Similarly, axes could be deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry just noticed #3886, will take some time to investigate.
From the behavior perspective, I assume
What I haven't decided: if the new option being set doesn't have axes specifed, should we assume the old axes being used? 2 situations when creating chart:
|
@xg-wang good questions! If there are axes specified in the new options, we should replace the old axes with the new axes. This may end up being too complicated to do. I think if there are no new axes then we should keep the old ones and perhaps throw an error, or put a console warning. @simonbrunel looping you in for your thoughts |
7a42827
to
3557635
Compare
@etimberg This is the first time I made quite some changes to Chat.js so please advise if anything's wrong or breaking the style. |
Previously |
The "scales" arrays strikes back :\ I agree that it looks hacky and since we are planning to move away from these arrays, I'm a bit worry of introducing this sync logic. There are so many way to update the options in a way that would break the update (I think I'm wondering if it would not be easier and more robust to simply destroy and recreate all scales at every update? what would be the consequences to do that instead of trying to re-sync scales? why would we want to sync scales in the first place (it doesn't support animations)? |
Yes it would be much more easier and cleaner if destroy every time. |
@simonbrunel |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have to update these tests to pass CI, but not sure these would affect some users' use cases or not.
@simonbrunel once consequence is a performance penalty for update. Now, we have to re-merge all the axis options and see what changes. @xg-wang is it possible to profile these changes and see what the performance penalty looks like? |
@etimberg ok I'll profile and compare the two update strategy. |
src/core/core.controller.js
Outdated
scales[scale.id] = scale; | ||
} | ||
// clear up discarded scales | ||
helpers.each(updated, function(id, hasUpdated) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure that this loop is in the right place. I think it needs to happen after the entire outer loop has run. On the first iteration of the outer loop, only 1 scale will be updated and this will delete all the other axes
src/core/core.controller.js
Outdated
} | ||
chart.config.options = chart.options; | ||
|
||
chart.options = chart.config.options = newOptions; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since a new object has already been created, it should be more clear to just reset the options, the result is actually the same.
@@ -291,6 +297,14 @@ module.exports = function(Chart) { | |||
me.scale = scale; | |||
} | |||
}); | |||
// clear up discarded scales | |||
helpers.each(updated, function(hasUpdated, id) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@etimberg last commit here was definitely a mistake. Fixed here.
So now whenever user specify a scale with a new id
or the type
is changed, user lose the reference to the old scale.
@@ -314,6 +328,7 @@ module.exports = function(Chart) { | |||
|
|||
if (meta.controller) { | |||
meta.controller.updateIndex(datasetIndex); | |||
meta.controller.linkScales(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I came across this when I tried to update scales with different id
- dataset._meta
contains scales id which didn't update.
I check the scales id of meta
here, relink the scale if discarded.
I'm not sure whether I missed anything else, please point out if there are. It's a little bit too many configs here : P
samples/scales/toggle-type.html
Outdated
document.getElementById('randomizeData').addEventListener('click', function() { | ||
type = type === 'linear' ? 'logarithmic' : 'linear'; | ||
window.myLine.options.title.text = 'Chart.js Line Chart - ' + type; | ||
window.myLine.options.scales = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the type of the scale was to be changed, the scales
object has to be created instead of modify the property. This is for ticks
is still using the old type scale's ticks
- and is being merged when updating the options.scales
object.
I think we should suggest updating scales
options by recreating a whole object unless user is confident there is nothing wrong there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@xg-wang I am ok with that stipulation as long as we add it to the documentation
rebuild scales every timenew
update
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Tested it out and it worked nicely.
1 last thing for the sample. It should be added to https://github.com/chartjs/Chart.js/blob/master/samples/samples.js so that it appears on the sample page
samples/scales/toggle-type.html
Outdated
document.getElementById('randomizeData').addEventListener('click', function() { | ||
type = type === 'linear' ? 'logarithmic' : 'linear'; | ||
window.myLine.options.title.text = 'Chart.js Line Chart - ' + type; | ||
window.myLine.options.scales = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@xg-wang I am ok with that stipulation as long as we add it to the documentation
samples/scales/toggle-type.html
Outdated
<div style="width:75%;"> | ||
<canvas id="canvas"></canvas> | ||
</div> | ||
<button id="randomizeData">Randomize Data</button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nit] We should rename this to "Change scale type" or something similar.
@etimberg Great! Should I also squash these changes to 1 commit? There are several reverts. |
@xg-wang squashing to one commit would be great. One last thing, if you could also update the documentation regarding |
739635a
to
62098c2
Compare
docs/developers/updates.md
Outdated
``` | ||
|
||
Scales can be updated separately without changing other options. | ||
It is recommended to update scales by creating a new object rather than mutating the properties to be changed, unless you are confident all scales options would update as you wish - especially when upating type of the scale. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this ok? Or is it better to just recommend update as a new object when changing type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's easier to just suggest creating a new object as needed. It will hopefully avoid some github issues later
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated with code snippet
62098c2
to
d0ea25a
Compare
(Needed to patch in chartjs/Chart.js#4198 In order to get chartjs/Chart.js#4939 Axis type switching to work)
* Put the url being tested on the page * Allow setting of log scale on either axis (Needed to patch in chartjs/Chart.js#4198 In order to get chartjs/Chart.js#4939 Axis type switching to work) * Allow the setting of min on X axis too Ignore 0 for min when in log * Smaller chart.js with all the fixes 0 log is ok now
hey can we get this in ? what is holding it up ? |
@ldemailly Sorry I've no idea.. @simonbrunel could you review this code? |
it's already accepted by 1 person but maybe you need to address the codeclimate lints ? |
@xg-wang sorry, really busy these last months, forgot about this PR. Reviewing right now! The CodeClimate issues was here before and don't need to be fixed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, thanks @xg-wang. We definitely need to get rid of this scale "arrays" and support a single map of scales instead. That would simplify everything, but I guess it needs to wait until v3.
config: {
scales: {
foo: { // the scale id
type: 'time',
position: 'bottom', // implicit x-axis
// ...
}
}
}
Thanks @simonbrunel . BTW what would be the expected time for V3? Looking forward to it. |
Nothing planned since we are not working on a v3 and we don't want to release it with APIs that we don't like. The idea (discussed with @etimberg) is to cleanup the v2 API to get really close to what we envision for a v3. That means we will deprecate stuff progressively, continue to introduce new features, then switching to v3 would basically consist in removing deprecated code and add features that are not possible in v2 (e.g. changing the scales options format would be quite complicated in v2 without breaking changes) |
@simonbrunel @etimberg would you guys be able to create a milestone in github for 3.0? Then we could file an issue to track stuff like this that we might want to consider for v3 so that we don't lose track of it |
Done @benmccann |
Great! Thanks! |
- allow options to be updated in-place or as a new object - re-merge new options and rebuild scales & tooltips - preserve reference to old scale if id/type not changed - related tests and new sample also added. - update document about options update - update doc and example
Cached plugin descriptors hold a reference on the plugin options, which break if the plugin options object is replaced. That case happens when the user updates the plugin options with a new object, but also during since the new config update logic (chartjs#4198) that now always clone the plugin options. The fix consist in explicitly invalidating that cache before updating the chart.
Cached plugin descriptors hold a reference on the plugin options, which break if the plugin options object is replaced. That case happens when the user updates the plugin options with a new object, but also since the new config update logic (chartjs#4198) that now always clones the plugin options. The fix consists in explicitly invalidating that cache before updating the chart.
Cached plugin descriptors hold a reference on the plugin options, which break if the plugin options object is replaced. That case happens when the user updates the plugin options with a new object, but also since the new config update logic (#4198) that now always clones the plugin options. The fix consists in explicitly invalidating that cache before updating the chart.
- allow options to be updated in-place or as a new object - re-merge new options and rebuild scales & tooltips - preserve reference to old scale if id/type not changed - related tests and new sample also added. - update document about options update - update doc and example
Cached plugin descriptors hold a reference on the plugin options, which break if the plugin options object is replaced. That case happens when the user updates the plugin options with a new object, but also since the new config update logic (chartjs#4198) that now always clones the plugin options. The fix consists in explicitly invalidating that cache before updating the chart.
#4197
When updating the options, should merge with the default value and add ids before setting them, just like when initializing.
And I think the function name should updateOptions since it really only touched the options.