Hello all!
I’m having a little bit of trouble with an output.
I created a layout with multiple buttons and a dropdown. These buttons have in their ids 1A, 2A, 3A, 1B, 2B, 3B, 1C, 2C, 3C, … and the dropdown A, B, C, …
I want to create a callback that changes the color of the buttons based on the dropdown value. If A: change all buttons in which the A is in their ID, …
I created this callback but its not working:
def _set_feedback(self, app):
@app.callback(
Output({'type': "button", 'index': MATCH}, "color"),
Input("dropdown", "value"),
prevent_initial_call = True
)
def change_color(value):
if value == "A":
return "danger"
Any suggestions?
AIMPED
August 7, 2023, 6:13am
2
Hi @dash_ploty_noob , welcome to the forums.
What is your index
in this case? Do you need your index
for other matching callbacks?
Thank you @AIMPED !!
The ids are the following id={‘type’: “button”, ‘index’: letter+str(number)}. The buttons are generated in a for cycle from a list of letters and numbers
AIMPED
August 8, 2023, 9:28am
4
Now I understand what you are after. Actually pattern matching callbacks don’t work like that.
The MATCH
does not refer to value
but rather to a matching component. Take this example:
from dash import Dash, html, Input, Output, MATCH, ctx
app = Dash(__name__)
app.layout = html.Div(
[
html.Div(
[
html.Button(f'button_{idx}', id={'type': 'btn', 'index': idx})
for idx in range(3)
]
),
html.Div(
[
html.Div(id={'type': 'out', 'index': idx})
for idx in range(3)
]
)
]
)
@app.callback(
Output({'type': 'out', 'index': MATCH}, 'children'),
Input({'type': 'btn', 'index': MATCH}, 'n_clicks'),
prevent_initial_call=True
)
def output(n_clicks):
triggered_index = ctx.triggered_id.index
return f'button wth index {triggered_index} has been clicked {n_clicks} times.'
if __name__ == '__main__':
app.run(debug=True)
mred pmcb
AIMPED
August 8, 2023, 10:38am
5
It’s not pretty but it does the job:
from dash import Dash, html, dcc, Input, Output, ALL, State
BTN_NUM = 10
CHARS = 'ABCDEFG'
COLORS = ['red', 'green', 'blue', 'yellow', 'white', 'purple', 'orange']
# len(COLORS) has to be the same as len(CHARS)
app = Dash(__name__)
app.layout = html.Div(
[
html.Div(
[
html.Div(
[
html.Button(
id={'type': f'btn_{char}', 'index': idx},
children=f'button_{char}_{idx}',
style={'background-color': 'gray'}
)
for idx in range(BTN_NUM)
]
)
for char in CHARS
]
),
html.Div(
[
dcc.Dropdown(
id='drop',
options=list(CHARS)
),
html.Button(
id='reset',
children='RESET'
)
]
)
]
)
@app.callback(
[
Output({'type': f'btn_{char}', 'index': ALL}, 'style')
for char in CHARS
],
Input('drop', 'value'),
[
State({'type': f'btn_{char}', 'index': ALL}, 'style')
for char in CHARS
],
prevent_initial_call=True
)
def output(value, *states):
# find index of selected char in CHARS
outer_idx = CHARS.index(value)
# assign color to selected char
color = COLORS[outer_idx]
# loop over values and change according to selection
for i in range(BTN_NUM):
states[outer_idx][i] = {'background-color': color}
return states
@app.callback(
[
Output({'type': f'btn_{char}', 'index': ALL}, 'style', allow_duplicate=True)
for char in CHARS
],
Input('reset', 'n_clicks'),
prevent_initial_call=True
)
def output(_):
return [
[{'background-color': 'gray'}] * BTN_NUM
] * len(CHARS)
if __name__ == '__main__':
app.run(debug=True)