Repository navigation
[BUG] Callback executes but return value has no effect #1075
Description
Describe your context
dash 1.7.0
dash-core-components 1.6.0
dash-html-components 1.0.2
dash-renderer 1.2.2
dash-table 4.5.1
Tried on Google Chrome and Firefox
Describe the bug
Hi, I have an issue with a callback. It executes just fine (I can see print outs from it) but the return value has no effect.
Basically I hooked a Div with a custom class (a spinner) to a button. The div is at the beginning hidden. When the button is pressed, the callback changed the style of that div to remove "visibility" attribute. That button also trigger some operations happening on the server side, and when this operation is finished, it fills a Dash table and notify a hidden Div that the operation is finished. That hidden Div is also connected to my spinner to changed the style back to add the 'visibility': "hidden" back.
The code looks like this:
@app.callback(
[
dash.dependencies.Output('process-button-trigger-sync', 'n_clicks'),
dash.dependencies.Output('process-button-trigger-fetch-messages', 'n_clicks')
],
[
dash.dependencies.Input('process-button', 'n_clicks')
]
)
def trigger_process_button_actions(n_clicks):
print_log(request,f"process-button has been triggered: {n_clicks}")
if n_clicks:
return [ 1, 1 ]
else:
raise PreventUpdate()
@app.callback(
dash.dependencies.Output('process-status-icon-div', 'style'),
[
dash.dependencies.Input('process-button-trigger-sync', 'n_clicks'),
dash.dependencies.Input('finished-fetching-messages', 'n_clicks'),
],
[
dash.dependencies.State('process-status-icon-div', 'style')
]
)
def show_loading_state(started, finished, current_style):
print_log(request,f"Checking loading state div visibility:")
ctx = dash.callback_context
print_log(request,f"Style: {current_style}")
if ctx.triggered:
for evt in ctx.triggered:
comp = evt['prop_id'].split('.')[0]
if comp == "process-button-trigger-sync":
if started:
print_log(request,"should show loading state")
return loading_state_div_style
else:
raise PreventUpdate()
else:
print_log(request,"should hide loading state")
return {**loading_state_div_style, **{'visibility': "hidden"}}
@app.callback(
[
dash.dependencies.Output('msg-table', 'children'),
dash.dependencies.Output('finished-fetching-messages', 'n_clicks')
],
[
dash.dependencies.Input("process-button-trigger-fetch-messages", "n_clicks")
]
)
def get_messages(n_clicks):
[... do stuffs ...]
return [ [table_content], 1 ]It works the first time I click on the button , but any subsequent click generate the proper table content for and triggers the callback (I can see it in the logs), but the
does't get its style changed.
The logs shows:
2020-01-09 17:50:05.174789] [10.50.46.15] process-button has been triggered: 1
[2020-01-09 17:50:05.212320] [10.50.46.15] Checking loading state div visibility:
[2020-01-09 17:50:05.212419] [10.50.46.15] Style: {'display': 'inline-block', 'padding': '0% 6% 0% 1%', 'vertical-align': 'middle', 'visibility': 'hidden'}
[2020-01-09 17:50:05.212520] [10.50.46.15] should show loading state
[2020-01-09 17:50:05.349895] [10.50.46.15] Getting messages...
[2020-01-09 17:50:06.155847] [10.50.46.15] Checking loading state div visibility:
[2020-01-09 17:50:06.155985] [10.50.46.15] Style: {'display': 'inline-block', 'padding': '0% 6% 0% 1%', 'vertical-align': 'middle'}
[2020-01-09 17:50:06.156095] [10.50.46.15] should hide loading state
[2020-01-09 17:50:23.486135] [10.50.46.15] process-button has been triggered: 2
[2020-01-09 17:50:23.533177] [10.50.46.15] Checking loading state div visibility:
[2020-01-09 17:50:23.533278] [10.50.46.15] Style: {'display': 'inline-block', 'padding': '0% 6% 0% 1%', 'vertical-align': 'middle', 'visibility': 'hidden'}
[2020-01-09 17:50:23.533379] [10.50.46.15] should show loading state
[2020-01-09 17:50:23.664761] [10.50.46.15] Getting messages...
[2020-01-09 17:50:24.436566] [10.50.46.15] Checking loading state div visibility:
[2020-01-09 17:50:24.436679] [10.50.46.15] Style: {'display': 'inline-block', 'padding': '0% 6% 0% 1%', 'vertical-align': 'middle', 'visibility': 'hidden'}
[2020-01-09 17:50:24.436779] [10.50.46.15] should hide loading stateAs you can see (hopefully), The first time the button is pressed, the current style of the Div has the "hidden" attribute. When the operation is over ("Getting messages" message), the callback is triggered again, and the current style doesn't have the hidden attribute (which is expected).
The second time around, the callback is triggered properly again, but the spinner never showed. Indeed, one can see that after the operation completes, and the current style of the div is printed, it has the "hidden" attribute while it should have been removed previously.
Expected behavior
When the callback is triggered and executed, the return value should have an effect.
I hope this is clear enough. This is taken from a big piece of code so hopefully I managed to make it readable.
Activity
zupalex commentedon Jan 9, 2020
Using what I posted here as a minimal example, I can get it to work properly by removing the intermediate Div and and . Instead, if I use the directly as an input for both callbacks, and use children as an input for the second callback instead of , it updates just fine.
However I would expect this to work, especially since the callback fires properly, just that the return value is not registered.
The reason why I split it like that at the first place is that in the full code, I was using as an input for multiple callbacks (5 total), and some would not fire at all or fire randomly when the button was pressed. Using it as an input for only one callback and using several Div to propagate the callback made the appropriate callbacks fire, but then the return values are "ignored" as described in the first post.
mjclawar commentedon Feb 15, 2020
Running into (I think) a similar issue with callbacks being ignored with Dash releases post 1.6.1. The callback does execute (and I can even see it correct in the network requests in the console), but does not have the intended effect on the layout.
Does your example work when you use
dash==1.6.1and break when you usedash==1.7.0?mjclawar commentedon Feb 15, 2020
It may have something to do with this change (I would assume it's in the dash-renderer JS since it's making it to the client correctly):
v1.6.1...v1.7.0#diff-15692ba768eeab56e95aa409ab7c19b7R370-R392
Also potentially related to #1071 and #1053
alexcjohnson commentedon Mar 6, 2020
I suspect this will be fixed by #1103 (which includes tests for #1053 and #1071) but it's hard to tell for sure without a complete reproduction case. If one of you would be able to post a full app showing the bug I'd be happy to try it and include a test for it - or, you can try the
475-wildcardsbranch on your own, but beware if you pull that branch down you need to rebuild the renderer bundle before running the app.matsujju commentedon Jan 12, 2021
Hey @alexcjohnson
I am having similar issue but my Output is single. The result of callback is printing in console but not showing in Dashboard. I have also posted in community channel. You can look here.
Here is the code of mine:
alexcjohnson commentedon Jan 12, 2021
I continued the discussion with @matsujju on the community post. The rest of this most likely was handled by #1103 but if there's anything else along these lines please open a new issue.