Fighting with callback with multiple outputs

I’m trying to use Multi Output callbacks. It seems to work, but I get:

dash.exceptions.InvalidCallbackReturnValue: The callback ..tile1.style...tile2.style.. is a multi-output. Expected the output type to be a list or tuple but got None.

Anyone that understand what I’m doing wrong? (Dash 1.1.1, code below)

KnutUH

import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html

app_tab_labels = ['Default view', 'First tile', 'Second tile']

app = dash.Dash()
app.layout = html.Div([
    html.Nav([
        dcc.Tabs(id="app-tabs", value=app_tab_labels[0], children=[
            dcc.Tab(label=app_tab_labels[0], value='default-tile'),
            dcc.Tab(label=app_tab_labels[1], value='tile-one'),
            dcc.Tab(label=app_tab_labels[2], value='tile-two'),
        ])
    ]),
    html.Div([
        html.H2("First tile")
    ], id='tile1'),
    html.Div([
        html.H2("Second tile")
    ], id='tile2')
])


@app.callback([Output('tile1', 'style'),
               Output('tile2', 'style')],
              [Input('app-tabs', 'value')])
def render_content(tab):
    if tab == 'default-tile':
        return [{'display': 'inline-block'}, {'display': 'inline-block'}]
    elif tab == 'tile-one':
        return [{'display': 'block'}, {'display': 'none'}]
    elif tab == 'tile-two':
        return [{'display': 'none'}, {'display': 'block'}]


if __name__ == '__main__':
    app.run_server(debug=True, port=8060)

Your problem is here. Since you have no final “else” or a return statement then your function is terminating without returning anything!

This is probably because in your if/else block you are checking for equality with tab values, however on the first load the value of “tab” is actually the tab label.

Change your code to the following (or use a debugger to inspect the value of tab) and you can clearly see the value of tab is “Default View” when the page first loads.

print(tab)

if tab == 'Default view':
    return [{'display': 'inline-block'}, {'display': 'inline-block'}]
elif tab == 'First tile':
    return [{'display': 'block'}, {'display': 'none'}]
elif tab == 'First tile':
    return [{'display': 'none'}, {'display': 'block'}]

If you want to ignore this then use something like:

if tab == 'Default view':
    return [{'display': 'inline-block'}, {'display': 'inline-block'}]
elif tab == 'First tile':
    return [{'display': 'block'}, {'display': 'none'}]
elif tab == 'First tile':
    return [{'display': 'none'}, {'display': 'block'}]

else:
    raise PreventUpdate

Thanks!

The first load sends the label and the next ones sends the value, why? Anyway, the `raise PreventUpdate´ will fix the problem, but I still need to test against the values (or make labels and values the same).

I’m new at this and started from the example in the documentation and I think the example will have the same problem ;-(

KnutUH

Probably because you are incorrectly setting the value attribute of Tabs

Thanks. :roll_eyes: They say that the insects are important, that’s why I make as many BUGS as I can!