Open
Description
Similar to ALLSMALLER
but doesn't asume that id index are numeric and sequential
Use case
General description
- There's a set of components with the same pattern-matching id type.
- Based on an interaction with one of those components (or with another component with the same pattern-matching id index), something about it will change.
- That same property will also change in the rest of the components of the set, but with a different value.
Example
- We have 6 clickable cards.
- Each clickable card is an html.Div with pattern-matching id
{'type':'card,'index': f"card_{i}"}
wrapped in an html.A with pattern-matching id{'type':'invisible_button,'index': f"card_{i}"}
. - When a user clicks one card, its
style
changes to HIGHLIGHT_STYLE (red) and thestyle
of the rest changes to DEFAULT_STYLE (black).
Screen.Recording.2025-03-10.at.18.10.46.mov
Desired behavior/code
@callback(
Output({'type':'card','id': MATCH}, 'style'),
Output({'type':'card','id': ALLELSE}, 'style'),
Input({'type':'invisible_button','id': MATCH}, 'n_clicks'),
)
def restore_card_format(n_clicks):
return HIGHLIGHT_STYLE, [DEFAULT_STYLE]*5
Current behavior/code
@callback(
Output({'type':'card','id': ALL}, 'style'),
Input({'type':'invisible_button','id': ALL}, 'n_clicks'),
)
def restore_card_format(n_clicks):
return DEFAULT_STYLE
@callback(
Output({'type':'card','id': MATCH}, 'style'),
Input({'type':'invisible_button','id': MATCH}, 'n_clicks'),
)
def highlight_card(n_clicks):
return HIGHLIGHT_STYLE
Using the above code produces an error like this:
In the callback for output(s): {"id":MATCH,"type":"card"}.style Output 0 ({"id":MATCH,"type":"card"}.style) overlaps another output ({"id":ALL,"type":"card"}.style) used in a different callback.
Workaround - current way to implement this functionality:
from dash import Dash, Input, Output, callback, html, dcc, ALL, MATCH, ctx
app = Dash()
server = app.server
DEFAULT_STYLE = {
"height":"200px",
"width":"200px",
"margin":"5px",
"background-color": "black",
"color":"white"
}
HIGHLIGHT_STYLE = {
"height":"200px",
"width":"200px",
"margin":"5px",
"background-color": "red",
}
app.layout = html.Div([
html.A(
html.Div(
id={'type':'card','index': f"card_{i}"},
style=DEFAULT_STYLE,
children=f"card_{i}"
),
id={'type':'invisible_button','index': f"card_{i}"},
)
for i in range(6)
], style={"display":"inline-flex"})
@callback(
Output({'type':'card','index': ALL}, 'style'),
Input({'type':'invisible_button','index': ALL}, 'n_clicks'),
prevent_initial_call=True
)
def highlight_card(n_clicks):
selected_card_id = ctx.triggered_id["index"]
# this is how ctx.outputs_list looks like
# [{'id': {'index': 'card_0', 'type': 'card'}, 'property': 'style'}, {'id': {'index': 'card_1', 'type': 'card'}, ...]
new_styles = [HIGHLIGHT_STYLE if card["id"]["index"]==selected_card_id else DEFAULT_STYLE for card in ctx.outputs_list]
return new_styles
app.run(debug=True)