Skip to content

Bindings #1002

Closed
Closed
@rreusser

Description

@rreusser

As 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

cc: @etpinard @chriddyp @alexcjohnson

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions