Skip to main content

Plotly Events

Plotly events make it possible to trigger actions based on front-end interactions with Plotly objects such as clicks, mouse hovers, widget or tool interactions, etc.

Setting up a Plotly Event

Plotly components can have an optional events param. This takes Plotly.Event objects which are defined by the following attributes:

  • event_name defines the Plotly.js event to respond to such as a click or hover
  • actions the Dara actions that should be performed when that event is triggered, for example update a Variable with the coordinates of the point selected. This enables a dynamic layout based on an user's interaction with the plot.
  • custom_js this js string is designed to update the figure, e.g. when hovering to change a dot color in the plot. To learn more about this is worth checking the Plotly.js events examples.

To further understand this, imagine you want to create a scatter plot that when hovering the color of the point selected changes to pink and when clicked turns green. You also want to show the coordinates of the point you are interacting with in your app.

First event_name, you will need plotly_click and plotly_hover, which could also be passed with the help of the component dara.components.plotting.plotly.PlotlyEventName enum as Plotly.EventName.CLICK and Plotly.EventName.HOVER.

Next actions for both we will need to update a Variable with the coordinates associated with the interacted point. For this you can add the following action:

@action
async def update_some_var(ctx: action.Ctx):
await ctx.update(
variable=some_var,
value={
"x": ctx.input[0]["x"],
"y": ctx.input[0]["y"],
},
)

In the case of hover and click events the action context will receive an object containing the data points interacted with. To obtain the coordinates we can access the first element, this is the singular data point you clicked. And then return the x and y values.

Finally it comes down to custom_js this is in charge of updating the figure based on some event. In this case you want to change the color of a data point. The custom_js function receives two arguments that can be accessed. The first is data containing the data of the event performed, the data point clicked/hovered, and the second is the figure, which defines the graph state.

// data contains the data points interacted, we get pointNumber which contains the index of the point interacted with
const pn = data.points[0].pointNumber;
// if color for the marker is set get that array otherwise create an array filled with the default color
const colors = data.points[0].marker?.color || new Array(figure.data[0].x.length).fill('#3796F6');
// updated the entry on the array corresponding to the selected data point to be a different color
colors[pn] = '#C54C82';
// update the figure to use this new color array
figure.data[0].marker = {...figure.data[0].marker, color: colors};

With that you have all the ingredients to create a Plotly event, full code to the example is shown below:

from dara.core import (
Variable,
py_component,
ConfigurationBuilder,
ComponentInstance,
get_icon,
action,
)
from dara.components import Stack, Text, Plotly
import plotly.graph_objects as go


# create a simple plotly figure
def event_example():
# Create data
x = [1, 2, 3, 4, 5]
y = [2, 4, 1, 3, 5]

# Create scatter plot
fig = go.Figure(data=go.Scatter(x=x, y=y, mode="markers", marker=dict(size=10)))

return fig


some_var = Variable("No point selected")


# py_component to show the coordinate values stored in the Variable
@py_component
def show_var(var):
return Text(str(var))


@action
async def update_some_var(ctx: action.Ctx):
await ctx.update(
variable=some_var,
value={
"x": ctx.input[0]["x"],
"y": ctx.input[0]["y"],
},
)


def plotly_page_content() -> ComponentInstance:
return Stack(
Plotly(
event_example(),
events=[
Plotly.Event(
# Can add event name as a string or from Plotly.EventName
event_name=Plotly.EventName.CLICK,
# The code to be executed when clicking on a point
custom_js="""
const pn = data.points[0].pointNumber;
const colors = data.points[0].marker?.color || new Array(figure.data[0].x.length).fill('#3796F6');

colors[pn] = '#2CB85C';
figure.data[0].marker = {...figure.data[0].marker, color: colors}
""",
actions=[update_some_var()],
),
Plotly.Event(
event_name=Plotly.EventName.HOVER,
custom_js="""
const pn = data.points[0].pointNumber;
const colors = data.points[0].marker?.color || new Array(figure.data[0].x.length).fill('#3796F6');

colors[pn] = '#C54C82';
figure.data[0].marker = {...figure.data[0].marker, color: colors};
""",
actions=[update_some_var()],
),
],
),
show_var(some_var),
)


config = ConfigurationBuilder()
config.add_page(
name="Plotly", content=plotly_page_content(), icon=get_icon("chart-line")
)