Is there a better way to perform multiple output with Dash by Plotly?

Based on this, there is a way.

What you can do is to update a hidden "Signal Element" (this can be a text input for example), which in turn, updates the two main elements.

Run the get_data(filter) once, and store the result in a global variable. Then instead of updating element_1 and element_2, update that signal element.

result = []

@app.callback(
dash.dependencies.Output('signal', 'value'),
[dash.dependencies.Input('filter', 'value')])
def callback_signal(filter):
    global result
    result = get_data(filter)
    return filter

@app.callback(
dash.dependencies.Output('element_1', 'children'),
[dash.dependencies.Input('signal', 'value')])
def callback_element_1(filter):
    return result.el1


@app.callback(
dash.dependencies.Output('element_2', 'children'),
[dash.dependencies.Input('signal', 'value')])
def callback_element_2(filter):
    return result.el2

In my case, I was using Dash in a single user environment, and using the global variable was not an issue. In case you have multiple users who will be running the app at the same time, the alternatives are available, and you can find them in the same link.


Multi output callbacks support was merged in Dash (2019/03/01).

  • See GitHub pull-request: Multi output callbacks support

  • See announcement: Multiple outputs in Dash - Now Available!


What if you can compose the action listeners in an outer function? using Oleh's example

def setup_action_callbacks(app):
    result = []

    @app.callback(
    dash.dependencies.Output('signal', 'value'),
    [dash.dependencies.Input('filter', 'value')])
    def callback_signal(filter):
        result = get_data(filter)
        return filter

    @app.callback(
    dash.dependencies.Output('element_1', 'children'),
    [dash.dependencies.Input('signal', 'value')])
    def callback_element_1(filter):
        return result.el1


    @app.callback(
    dash.dependencies.Output('element_2', 'children'),
    [dash.dependencies.Input('signal', 'value')])
    def callback_element_2(filter):
        return result.el2

Such that:

def get_app_layout(app):
    setup_action_callbacks(app)
    return html.Div()

app = DjangoDash(name="a_nice_name", app_name="a_nice_app_name")
app.layout = get_app_layout(app)

Now, Plotly Dash supporting multiple outputs in single event. This is with latest version of dash==0.38.0rc1

@app.callback(
    [
        Output('output1', 'children'), 
        Output('output2', 'children')
    ],
    [
        Input('output-btn', 'n_clicks'),
        State('output-btn', 'n_clicks_timestamp')
    ]
)
def on_click(n_clicks, n_clicks_timestamp):
    if n_clicks is None:
        raise PreventUpdate

    return n_clicks, n_clicks_timestamp

Git Sample