How to create custom actions
This guide demonstrates the usage of custom actions, an idea that shares similarities with, but is not identical to callbacks in Dash
. If you want to use the Action
model to perform functions that are not available in the built-in action functions, you can create your own custom action. Like other actions, custom actions could also be added as an element inside the actions chain, and it can be triggered with one of many dashboard components.
Simple custom action
Custom actions enable you to implement your own action function. Simply do the following:
- define a function
- decorate it with the
@capture("action")
decorator - add it as a
function
argument inside theAction
model
The following example shows how to create a custom action that postpones execution of the next action in the chain for t
seconds.
Simple custom action
import vizro.models as vm
import vizro.plotly.express as px
from vizro import Vizro
from vizro.actions import export_data
from vizro.models.types import capture
from time import sleep
@capture("action") # (1)!
def my_custom_action(t: int):
sleep(t)
df = px.data.iris()
page = vm.Page(
title="Simple custom action",
components=[
vm.Graph(
figure=px.scatter(df, x="sepal_length", y="petal_width", color="species")
),
vm.Button(
text="Export data",
actions=[
vm.Action(function=export_data()),
vm.Action(function=my_custom_action(t=2)),
vm.Action(function=export_data(file_format="xlsx")),
]
)
]
)
dashboard = vm.Dashboard(pages=[page])
Vizro().build(dashboard).run()
Run and edit this code in Py.Cafe
- We define a custom action
my_custom_action
using the@capture("action")
decorator. This action takes an integert
and pauses execution fort
seconds. It's used here to delay the subsequentexport_data
action in the chain.
Custom actions are currently only possible via Python configuration.
Interact with inputs and outputs
When a custom action needs to interact with the dashboard, it is possible to define inputs
and outputs
for the custom action.
inputs
represents dashboard component properties whose values are passed to the custom action function as arguments. It is a list of strings in the format"<component_id>.<property>"
(for example,"my_selector.value
").outputs
represents dashboard component properties corresponding to the custom action function return value(s). Similar toinputs
, it is a list of strings in the format"<component_id>.<property>"
(for example,"my_card.children"
).
Example of value
as input
The following example shows a custom action that takes the value
of the vm.RadioItem
and returns it inside a Card
component.
Display value
in Card
import vizro.models as vm
import vizro.plotly.express as px
from vizro import Vizro
from vizro.models.types import capture
df = px.data.iris()
vm.Page.add_type("components", vm.RadioItems)
@capture("action") # (1)!
def update_card_text(species):
return f"You selected species **{species}**"
page = vm.Page(
title="Action with value as input",
layout=vm.Grid(grid=[[0, 1]]),
components=[
vm.RadioItems(
id="my_selector",
title="Select a species:",
options=df["species"].unique().tolist(),
actions=[
vm.Action(function=update_card_text(), inputs=["my_selector.value"], outputs=["my_card.children"])
],
),
vm.Card(text="Placeholder text", id="my_card"),
],
)
dashboard = vm.Dashboard(pages=[page])
Vizro().build(dashboard).run()
Run and edit this code in Py.Cafe
- We define a custom action
update_card_text
using the@capture("action")
decorator. This action takes the selectedspecies
as input and returns a formatted string to be displayed in a Card.
Custom actions are currently only possible via Python configuration.
Example of clickData
as input
The following example shows how to create a custom action that shows the clickData
of a chart in a Card
component. For further information on the structure and content of the clickData
property, refer to the Dash documentation on interactive visualizations.
Display clickData
in Card
import vizro.models as vm
import vizro.plotly.express as px
from vizro import Vizro
from vizro.models.types import capture
df = px.data.iris()
@capture("action") # (1)!
def my_custom_action(show_species: bool, points_data: dict): # (2)!
clicked_point = points_data["points"][0]
x, y = clicked_point["x"], clicked_point["y"]
text = f"Clicked point has sepal length {x}, petal width {y}"
if show_species:
species = clicked_point["customdata"][0]
text += f" and species {species}"
return text
page = vm.Page(
title="Action with clickData as input",
components=[
vm.Graph(
id="scatter_chart",
figure=px.scatter(df, x="sepal_length", y="petal_width", color="species", custom_data=["species"]),
actions=[
vm.Action(
function=my_custom_action(show_species=True), # (3)!
inputs=["scatter_chart.clickData"], # (4)!
outputs=["my_card.children"],
),
],
),
vm.Card(id="my_card", text="Click on a point on the above graph."),
],
)
dashboard = vm.Dashboard(pages=[page])
Vizro().build(dashboard).run()
Run and edit this code in Py.Cafe
- We define a custom action
my_custom_action
using the@capture("action")
decorator. - This action takes a boolean
show_species
and a dictionarypoints_data
. It uses these to construct a descriptive string about a clicked point on a chart. The namesshow_species
andpoints_data
are arbitrary and do not need to match on to the names ofinputs
in any particular way. - When the
Action
is defined within theGraph.actions
, theshow_species
argument ofmy_custom_action
is statically bound toTrue
. - The
points_data
argument ofmy_custom_action
receives its value dynamically at runtime. This happens because theinputs
parameter ofvm.Action
is set to["scatter_chart.clickData"]
. When a user clicks on thescatter_chart
, the chart'sclickData
property (which contains details about the click event) is automatically passed as thepoints_data
argument tomy_custom_action
.
Custom actions are currently only possible via Python configuration.
Multiple return values
The return value of the custom action function is propagated to the dashboard components that are defined in the outputs
argument of the Action
model. If there is a single output
defined then the function return value is directly assigned to the component property. If there are multiple outputs
defined then the return value is iterated through and each part is assigned to each component property given in outputs
in turn. This behavior is identical to Python's flexibility in managing multiple return values.
Multiple return values
import vizro.models as vm
import vizro.plotly.express as px
from vizro import Vizro
from vizro.models.types import capture
@capture("action") # (1)!
def my_custom_action(points_data: dict):
clicked_point = points_data["points"][0]
x, y = clicked_point["x"], clicked_point["y"]
species = clicked_point["customdata"][0]
card_1_text = f"Clicked point has sepal length {x}, petal width {y}"
card_2_text = f"Clicked point has species {species}"
return card_1_text, card_2_text
df = px.data.iris()
page = vm.Page(
title="Example of a custom action with UI inputs and outputs",
layout=vm.Flex(), # (2)!
components=[
vm.Graph(
id="scatter_chart",
figure=px.scatter(df, x="sepal_length", y="petal_width", color="species", custom_data=["species"]),
actions=[
vm.Action(
function=my_custom_action(),
inputs=["scatter_chart.clickData"],
outputs=["my_card_1.children", "my_card_2.children"], # (3)!
),
],
),
vm.Card(id="my_card_1", text="Click on a point on the above graph."),
vm.Card(id="my_card_2", text="Click on a point on the above graph."),
]
)
dashboard = vm.Dashboard(pages=[page])
Vizro().build(dashboard).run()
Run and edit this code in Py.Cafe
- We define a custom action
my_custom_action
using the@capture("action")
decorator. This action takespoints_data
(dynamically populated fromscatter_chart.clickData
) as input, extracts details about the clicked point, and returns two strings,card_1_text
andcard_2_text
. - A
Flex
layout is used for the page to ensure theGraph
andCard
components are sized appropriately based on their content rather than being distributed evenly. - The two strings returned by
my_custom_action
are assigned in the same order here.
Custom actions are currently only possible via Python configuration.
Warning
Note that users of this package are responsible for the content of any custom action function that they write. Take care to avoid leaking any sensitive information or exposing to any security threat during implementation. You should always treat the content of user input as untrusted.