Bindings
See original GitHub issueAs controls get more capable in plotly, two-way binding becomes necessary. That is, a slider can change the frame, but the slider should also reflect the current frame when something else (e.g. a play button) changes it. This could also be the case for a marker size, a size ref, or a transform parameter. My current slider PR does this in sort of an ad hoc manner, but I really think it should be more general.
Proposal: bindings
Option 1:
Bindings are defined in the layout. For example:
"layout": {
"bindings": [{
"bind": "layout.updatemenus[0].active",
"to": "data[0].marker.color",
"lookup": {
"red": 0,
"green": 1,
"blue": 2
}
}]
}
In this example, bind
is the data that gets changed, to
is the item that’s observed for changes, and lookup
is an optional translation table that maps one to the other. Whenever a plotly event is emitted or when a relayout/restyle/update occurs, we quickly look through the bindings to see what’s changed (which shouldn’t be expensive enough that it’s a problem). If an item has changed, that item is written to the state of the plot. A plotly_bindingchange
event is emitted. All components (that’s the best I can do right now) must then look through their data to see if anything has changed and update accordingly.
Pros:
- Bindings link two parts of the plotly state, which accurately represents what’s actually happening
Cons:
- Updates take just a bit of thought and bookkeeping to do efficiently since this isn’t react
- requires a separate specification of bindings in addition to just the slider
- refers to other parts of the plotly json by integer index within the plotly json, which seems probably okay but 10% fragile
Option 2:
Bindings are defined in the component that needs them, e.g. a slider. The slider has:
"bindto": "data[0].marker.color"
Most of the logic is the same. (I’ve omitted the lookup table since, though it could be added, we should probably go to great lengths to generally avoid needing.) When a component binds to a variable, we register it as needing a lookup. We scan through those liberally since it’s fast, and when one changes, we emit an event. This case is a little simpler since we can emit plotly_bindingchange
with data {binding: 'data[0].marker.color', value: 'red'}
. The component sees its binding has changed and updates accordingly.
Pros:
- Requires less typing
- Collocates binding with the thing that uses the binding
- Avoids extra reference to
updatemenus[0].active
- The update pattern is maybe a bit more straightforward since the component directly knows about the binding.
Cons:
- Less general since it specifies a way of hooking up a component to a json item instead of hooking up a json item to a json item
Issue Analytics
- State:
- Created 7 years ago
- Comments:13 (13 by maintainers)
Top GitHub Comments
Don’t we already have that information in the definition of what each control does? ie if a control sets
marker.color
tored
then we can also tell we need to update it ifmarker.color
changes. If we want to calculate some binding table behind the scenes to make our lives easier that’s fine, but it seems redundant and confusing to have to specify this again.Also it’s possible for a control to be bound to more than one attribute, right? Like a button could change both
marker.color
andmarker.size
- in which case you’d have to check the state when either one of those changes, and only mark the control as active if the state matches all parts.first iteration completed in https://github.com/plotly/plotly.js/pull/1016