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
Initialize date adapter with chart options #6016
Conversation
If option are require, I would take a key for adapter options (like (edit, added more functions that would need options) |
I debated that as the other alternative. The tradeoff is that the options would need to be passed to every method requiring them, which would make calling the adapter methods harder. I also thought it might be difficult to envision every use case for every adapter. By passing the options into the adapter, they |
stateful: add: function(amount. unit) {
return do_stuff(this.options.requiredOption)
} stateless: add: function(amount, unit, options) {
return do_stuff(options.requiredOption);
} Some of these points make no difference, rest promote stateless design. |
This PR was the way I initially implemented adapters but after lot of discussions with @kurkle, we decided to go the static way. In #5960, there is a note about adding support for adapter options: passing an extra
These adapter options should be defined and collected at the time scale level, not (only?) at the chart level. Having two time scales (in the same chart) with different set of adapter options seems a valid use case to me, so a unique adapter instance at the chart level is wrong, it should be at least created at the scale level. An adapter should not be considered to target a specific feature (the time scale), we could decide to use it for anything that is date related. I would make the trailing That's why I'm still thinking we should keep adapters stateless. |
I agree both that we should collect options at the time scale level and that the options should be optional.
I'm not sure if affects how we pass in the options. We need to have some options object defined that gets passed in. It's just a question of do we pass them in via the constructor or method. My main concern about passing the options as parameters is that it makes the API harder to evolve. If we want to add a new optional parameter, does it go before or after the options? If the new parameter goes after the optional parameter then we're no longer following a consistent patter of putting them last. If it goes before, then we've broken backwards compatibility. Maybe we don't care at the moment since these are private, but I imagine at some point in the future we'll make them public and we'll have much less flexibility if the options are parameters. I typically think of a stateful object as one that is keeping track of state. There is no changing state here however. One way to be sure there's no changing state would be to call |
There's not a huge difference between approaches. |
I'm really divided between both approaches: #6016: I feel there is something wrong with creating multiple instances of an adapter. We will need to create one adapter per feature (currently, one adapter per time scale). I'm not worry about performance but it will make the state synchronization more complex than #6045 since we will need to update adapter options (or recreate new adapters) on every #6045: I like the simplicity of this stateless approach, one adapter for the whole app and no need to synchronize options. However, I have the same concern as @benmccann about how One idea to make #6045 more future proof would be to take the same direction as plugins, i.e. always pass two arguments to each adapter method: For example: adapter: {
parse: function(args, options) { ... }
diff: function(args, options) { ... }
//...
}
parse({value: '2019', format: 'AAAA'}, options)
diff({min: 1234, max: 4567, unit: 'hour'} ,options) I think I like it because it makes the API stable in case we need to add or remove arguments (even more stable than the two current approaches). We discussed that point a bit with @kurle but it seems a bit overkill for this minimal adapter interface until v3. But I would maybe still consider it to avoid calls like |
The args approach does solve the issues of API evolution and passing Original code:
With args:
I think I probably prefer the original #6045 to having an args object If we wanted an adapter per time scale then creating it during |
Some quick thoughts of args approach Pros:
Cons:
|
We started to use this way for our plugin hooks for exactly the same ordering issues, but we also decided to go that way for the controller @benmccann the correct example is:
I'm not sure why: let's say tomorrow we decide to remove one argument other than Though, that was a suggestion, which I think I prefer if we go with #6045, but I'm still open to discuss the dynamic approach of that PR. Note that even if the API is private, we still need to not introduce breaking change for external adapters. |
@benmccann can you update this PR with adapters created in the time scale during update, and picking adapter options from the scale options (the same I guess as #6045). Also, adapters shouldn't define a new class but instead override the base class ( Then it will be easier to compare both solutions with the same behavior. |
b3142df
to
1f30296
Compare
I pushed a new version of this PR that creates the adapter during |
Ok, let's iterate a bit more on this one which I think I tend to prefer. |
18f94ed
to
1a609da
Compare
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 starting to like this approach better
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.
Maybe add some documentation about where to specify adapter options, or should that be left to adapters?
My opinions is to point the location here and to consult adapter docs for available options.
For now, I think it might be best to leave the documentation to the individual adapters because the built-in moment adapter doesn't specify any options and so might confuse people who are using that one to see options mentioned but then not find any. If you're using the Luxon adapter or another one then the options can be made fairly prominent in those docs |
I agree, but for other adapters, the location that is passed to the adapter is not up to the adapter, but core. So I was thinking something like: "If you are using an external adapter that supports or needs options, those are passed from |
Ok. I added a line to the docs. Let me know what you think |
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.
It looks great, thanks @benmccann for all the changes.
@@ -586,7 +593,7 @@ module.exports = Scale.extend({ | |||
break; | |||
case 'auto': | |||
default: | |||
timestamps = generate(min, max, me.getLabelCapacity(min), options); | |||
timestamps = generate(me, min, max, me.getLabelCapacity(min), options); |
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.
remove the extra options
Opening for discussion purposes
I use Chart.js to plot a chart for each stock in my portfolio. Most are US stocks traded in the NYC timezone. However, some are UK stocks traded in the London timezone. With the current global date adapter I cannot set a different time zone for each stock chart. One idea I had for this was to make a chart option that is accessible to the date adapter and then pass the options into the adapter.
One thing that's a little messy is having to pass the adapter object around so much in the time scale. That's because the time scale has so many static methods. We could make these instance methods and cache the adapter on the scale which might make it a little cleaner.
Some tests are failing because they use a mock chart object which would need to be updated to define the new
chart.adapters._date
Related to #5960
Closes #6045