It would be nice to have the ability to update multiple outputs at once by specifying a list of Outputs and returning a tuple with the same number of outputs like in
@app.callback(
[Output('label1', 'children'),
Output('label2', 'children'),
],
[Input('dropdown', 'value'),
])
def cb_test_multi(value):
# some very complex calculation to be triggered only once when 'dropdown' changes
...
# result of calculation need to be pushed partly on 'label1' and partly on 'label2'
return "Hello", value
This would allow simplifying otherwise complex flow to update multiple components based on one change.
I second this. This would be incredibly useful. I like the design and look of Dash over alternate programs but the complexity of implementing this is holding me back from fully jumping in. It makes cross-linking multiple plots incredibly difficult compared to Bokeh or Holoviews.
Makes sense to me!
The app.callback syntax and the HTTP API were designed in such a way to allow something like this. I left this out of the initial release because I thought that it would cause some confusion among users (mainly: when do you use multiple callbacks vs multiple outputs) and I wanted to keep the surface area as small as possible for the initial release. There are some other alternatives to "sharing computations" among multiple callbacks (see https://plot.ly/dash/sharing-data-between-callbacks) but none of them are as simple as this proposal.
By introducing multiple outputs, there will be 2 ways to do the same thing: 2 outputs in a single callback vs 2 callbacks with a single output. It really only makes to use multiple outputs if the callback is expensive.
I can also imagine that some users will end up using multiple outputs in cases where two callbacks that executed in parallel would end up resulting in faster UI updates, for example:
@app.callback([Output(...), Output(...)], ...)
def update_outputs(*inputs):
val_1 = expensive_computation_1(*inputs)
output_1 = make_output(val_1)
# if this were a separate callback, the user could return output_1 at this point
# instead, they have lumped together all of the outputs into one function,
# blocking the UI from updating until all outputs are ready
val_2 = expensive_computation_2(*inputs)
output_2 = make_output(val_2)
return [output_1, output_2]
In any case, I'm 馃憤 with this now. It'll be a bit of work to implement, so if you would like to see this work please 馃憤 this issue. If you or your company needs this work expedited and can sponsor development, please reach out: https://plot.ly/products/consulting-and-oem/
btw, as much as Dash is a next-gen framework for full python UI on the browser, you may check APIStar (https://github.com/encode/apistar) that is a next-gen framework for Web API in python (after Django REST Framework, Flask, ...)
==> they took some very interesting way of crafting their API (type annotations instead of decorators to specify the arguments of the endpoint). As I discovered Dash and APIStar at the same time, I saw some possible cross-inspiration for Dash. Tell me what you think of the APIStar style and if you see some fit with Dash
Was this idea ever implemented?
I have an app that has 200 buttons. I'd rather append a list of outputs as I make the buttons and pass that to a single callback instead of having to write out 200 callback functions (as this would make my code very long/ugly).
Was this idea ever implemented?
It hasn't been, but it's still a good idea and I think we'll end up implementing before the end of the year.
(as this would make my code very long/ugly).
What I've done in these types of situations is create a look that generates these functions:
def create_callback(id):
def respond_to_button(*callback_args):
...
return respond_to_button
# Dash callbacks have to be defined up-front and therefore must anticipate
# all of the elements that might exist on the page
for i in range(100):
app.callback(
Output('output-{}'.format(i), 'some-property'),
[Input('button-{}'.format(i), 'n_clicks')])(
create_callback(i))
Hi @chriddyp, you mentioned the possibility of implementing this "next month" a few weeks ago. Do you have a specific date in mind?
you mentioned the possibility of implementing this "next month" a few weeks ago. Do you have a specific date in mind?
I do not. I will update this issue when we have a concrete date planned.
With regards to surface area, it could be a config option, e.g. enable_multiple_outputs -- requiring the user to explicitly turn it on will hopefully signpost it's for more advanced use, while keeping things simple for new users.
(I'm currently using @cache.memoize() on an expensive computation that's called by two callbacks/updates two outputs, but it feels like a bit of a hack)
you mentioned the possibility of implementing this "next month" a few weeks ago. Do you have a specific date in mind?
I do not. I will update this issue when we have a concrete date planned.
@chriddyp
Do you have an update on this issue?
Is there any progress regarding this issue? I would like to start an app with a lot of text field that have to be updated after user interaction. Without multiple updates it would be really a reason to abandon dash due to very complicated and overloaded function usage.
@cheak1974 It's coming #436
I have tried this multiple output but I got an error as
dash.exceptions.IncorrectTypeException: The output argument [<dash.dependencies
.Output object at 0x000000000804F898>, <dash.dependencies.Output object at 0x000
000000B16D748>] is not of type dash.Output.
Anyone has same issue?
@prasadovhal You tried the versions in #436 ?
pip install dash==0.36.0rc1
pip install dash-renderer==0.17.0rc1
Merged - will be in the next release, expected early next week 馃帀
Is there any update on this? Do we have this feature now?
Yes! It鈥檚 in release :) I鈥檝e been a happy user of this feature for some time
Check out the "Multiple Outputs" section of https://dash.plot.ly/getting-started-part-2
@mkhorton @alexcjohnson Thanks a ton guys for the prompt response.
How to get 0 outputs but only an eg Interval input? This errors:
@app.callback([],[d_dep.Input('interval_1', 'n_intervals')])
def dosome(input1):
pass
i prefer dash clientside over jpnotebooks
0 outputs doesn't really fit with the dash concept of a stateless back end - that's why it's an error. It's not an error with pattern-matching callbacks that just happen to match zero items, but then the callback won't even fire. If you really want a callback like this to fire I would suggest a dummy element - a hidden div, or a dcc.Store that you never use, something like that, and end the callback with a raise PreventUpdate or return no_update to short-circuit any re-rendering for performance purposes.
Most helpful comment
Makes sense to me!
The
app.callbacksyntax and the HTTP API were designed in such a way to allow something like this. I left this out of the initial release because I thought that it would cause some confusion among users (mainly: when do you use multiple callbacks vs multiple outputs) and I wanted to keep the surface area as small as possible for the initial release. There are some other alternatives to "sharing computations" among multiple callbacks (see https://plot.ly/dash/sharing-data-between-callbacks) but none of them are as simple as this proposal.By introducing multiple outputs, there will be 2 ways to do the same thing: 2 outputs in a single callback vs 2 callbacks with a single output. It really only makes to use multiple outputs if the callback is expensive.
I can also imagine that some users will end up using multiple outputs in cases where two callbacks that executed in parallel would end up resulting in faster UI updates, for example:
In any case, I'm 馃憤 with this now. It'll be a bit of work to implement, so if you would like to see this work please 馃憤 this issue. If you or your company needs this work expedited and can sponsor development, please reach out: https://plot.ly/products/consulting-and-oem/