-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Closed
Description
Desired behavior
This (or similar) would work:
dcc.Loading(
html.Button(id={"type":"button", "index":"two"}, children='Button 2', disabled=True),
target_components={'{"type":"button","index":"two"}':'disabled'}
),
like this does:
dcc.Loading(
html.Button(id="button_2", children='Button 2', disabled=True),
target_components={'button_2':'disabled'}
),
Current behavior
Screen.Recording.2025-06-26.at.13.49.48.mov
- I've tried all of the stringified combinations of the dict id I could think of.
target_components={{"type":"button", "index":"two"}:"disabled"}
won't work because dictionaries can't be the keys of other dictionaries; it'll generate this error: TypeError: unhashable type: 'dict'- This part of the source code is what handles the keys in target_components: https://github.com/plotly/dash/blob/dev/components/dash-core-components/src/components/Loading.react.js#L33
- dash==3.0.4
Code to reproduce and investigate the current behavior
from dash import callback, Dash, dcc, html, Input, Output, State, ctx
import time
app = Dash(__name__, suppress_callback_exceptions=True)
button_1 = html.Button(id={"type":"button", "index":"one"}, n_clicks=0, children='Trigger loading')
button_2 = html.Button(id={"type":"button", "index":"two"}, n_clicks=0, children='Button 2', disabled=True)
button_3 = html.Button(id="button_3", n_clicks=0, children='Button 3', disabled=True)
print({"type":"button", "index":"two"}) # {'type': 'button', 'index': 'two'} > option (7) should work
print({'type':'button', 'index':'two'}) # {'type': 'button', 'index': 'two'} > option (7) should work
radio_items = dcc.RadioItems(
id="target_props",
value="None",
options=[
{
"label":"(0) No target components (default behaviot, two loading animations will appear)",
"value":"None"
}, # None; any string would work
{
"label":'(1) DOUBLE quotes WITH spaces after punctuation and INDEX first: target_components=\'{"index": "two", "type": "button"}\'',
"value":'{"index": "two", "type": "button"}'
},
{
"label":'(2) DOUBLE quotes WITHOUT spaces after punctuation and INDEX first: target_components=\'{"index":"two","type":"button"}\'',
"value":'{"index":"two","type":"button"}'
},
{
"label":'(3) DOUBLE quotes WITH spaces after punctuation and TYPE first: target_components=\'{"type": "button", "index": "two"}\'',
"value":'{"type": "button", "index": "two"}'
},
{
"label":'(4) DOUBLE quotes WITHOUT spaces after punctuation and TYPE first: target_components=\'{"type": "button", "index": "two"}\'',
"value":'{"type":"button","index":"two"}'
},
{
"label":"(5) SINGLE quotes WITH spaces after punctuation and INDEX first: target_components=\"{'index': 'two', 'type': 'button'}\"",
"value":"{'index': 'two', 'type': 'button'}"
},
{
"label":"(6) SINGLE quotes WITHOUT spaces after punctuation and INDEX first: target_components=\"{'index':'two','type':'button'}\"",
"value":"{'index':'two','type':'button'}"
},
{
"label":"(7) SINGLE quotes WITH spaces after punctuation and TYPE first: target_components=\"{'type': 'button', 'index': 'two'}\"",
"value":"{'type': 'button', 'index': 'two'}"
},
{
"label":"(8) SINGLE quotes WITHOUT spaces after punctuation and TYPE first: target_components=\"{'type':'button','index':'two'}\"",
"value":"{'type':'button','index':'two'}"
},
]
)
app.layout = html.Div([
radio_items,
html.Br(),
dcc.Loading(button_1),
dcc.Loading(button_2, id="loading_pm"),
# target_components={{"type":"button", "index":"two"}:"disabled"}
# this won't work because dictionaries can't be the keys of other dictionaries
# it'll generate this error: TypeError: unhashable type: 'dict'
dcc.Loading(button_3)
])
@app.callback(
Output({"type":"button", "index":"two"}, 'disabled'),
Output("button_3", 'disabled'),
Input({"type":"button", "index":"one"}, 'n_clicks'),
State("button_3", 'disabled'),
prevent_initial_call=True)
def enable_button_filter(filter_query, disabled):
print(ctx.outputs_list)
# simulate a "long" process
time.sleep(1)
new_state = not disabled
return new_state, new_state
@app.callback(
Output("loading_pm", 'target_components'),
Input('target_props', 'value'),
prevent_initial_call=True
)
def update_target_components(val):
print({val:"disabled"})
return {val:"disabled"}
if __name__ == '__main__':
print(print(app.callback_map))
# fragment of output for the first callback:
# '..{"index":"two","type":"button"}.disabled...button_3.disabled..' > option (2) should work
# `{"index":"two","type":"button"}.disabled` > option (2) should work
app.run(debug=True)
Metadata
Metadata
Assignees
Labels
No labels