Dash Pattern Matching Callbacks: Match in Input but Not in Output
I Want to Use Dash Pattern Matching Callbacks' Match as an Input, Without Needing to Output to the Same Match. Imagine I Generate a Long, Random List of Items...
I want to use Dash pattern matching callbacks' MATCH as an Input, without needing to Output to the same MATCH. Imagine I generate a long, random list of items, from which a user may select any number of items. As they select each item, I want to append that item to a list in real time. It's a long list of 1,000+ items, so I don't want to see the whole ALL list, just the one they've selected in real time, so I can do a fast, efficient callback.
Something like the following:
from dash import Dash, dcc, html, Input, Output, State, MATCH, ALL
import dash_bootstrap_components as dbc
app = Dash(__name__, suppress_callback_exceptions=True)
# HTML table header and rows
header = html.Thead(html.Tr([html.Th("Add Part"), html.Th("Description")]))
rows = html.Tbody(
[
html.Tr(
[
html.Td(
dbc.Button(
"Add",
id={"type": "part_add", "index": i},
n_clicks=0,
),
),
html.Td(f"Index {i}"),
]
)
for i in range(1000)
]
)
app.layout = html.Div([
dcc.Store(id="my_list", storage_type="local", data=[]),
dbc.Table(
[header, rows],
bordered=True,
striped=True,
)
])
@app.callback(
Output("my_list", "data"),
Input({"type": "part_add", "index": MATCH}, "id"),
State("my_list", "data"),
)
def match_callback_test(
part_add_id,
my_list_data
):
return my_list_data.append(part_add_id)
Is the above possible, with a different pattern? I get a JavaScript console error if I run the above.
1 Answer
If MATCH is used, MATCH also needs to be on all of the Outputs. Just use ALL instead and check which id was triggered with ctx. Working example:
from dash import (
Dash,
dcc,
html,
Input,
Output,
State,
MATCH,
ALL,
ctx,
exceptions,
no_update,
)
import dash_bootstrap_components as dbc
app = Dash(__name__, suppress_callback_exceptions=True)
# HTML table header and rows
header = html.Thead(html.Tr([html.Th("Add Part"), html.Th("Description")]))
rows = html.Tbody(
[
html.Tr(
[
html.Td(
dbc.Button("Add", id={"type": "part_add", "index": i}, n_clicks=0,),
),
html.Td(f"Index {i}"),
]
)
for i in range(10)
]
)
app.layout = html.Div(
[
dcc.Store(id="my_list", storage_type="local", data=[]),
dbc.Table([header, rows], bordered=True, striped=True,),
]
)
@app.callback(
Output("my_list", "data"),
Input({"type": "part_add", "index": ALL}, "n_clicks"),
State("my_list", "data"),
)
def match_callback_test(part_add_id, my_list_data):
trigger = ctx.triggered_id
if trigger:
my_list_data.append(trigger["index"])
return my_list_data
return no_update
if __name__ == "__main__":
app.run(debug=True)