Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A Callback with a single Output wrapped in a list of length one, that returns a list, outputs a list [BUG] #1605

Closed
JonThom opened this issue Apr 26, 2021 · 3 comments

Comments

@JonThom
Copy link

JonThom commented Apr 26, 2021

Describe your context

dash                               1.19.0
dash-core-components               1.15.0
dash-html-components               1.1.2
dash-react-force-graph             0.0.1
dash-renderer                      1.9.0
dash-table                         4.11.2

Describe the bug

The following toy example callback has a single Output in the decorator, wrapped in a list.
The function returns its value inside a list.
If there were multiple Outputs, (e.g. two modals instead of one), this would work as expected.

import dash
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc 
import dash_html_components as html

app = dash.Dash(__name__)

app.layout = html.Div(
    children=[
        dbc.Modal("hi", id="modal"),
        dbc.Select(id="select",options=[{"label":"T","value":True}, {"label":"F","value":False}]
         )
    ]
)

@app.callback(    
    [
        Output("modal","is_open"),
    ],
    [
        Input("select","value")
    ],
)
def toggle_modal(bool):  
    return [bool]

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

Expected behavior

If bool is False, the modal component should receive the value False.

Observed behaviour

When, as in this example, there is a single output, the modal component receives it as a list.
A list of length 1 has a truthy value of True, so when coerced to boolean, the output is always True.

@JonThom
Copy link
Author

JonThom commented Apr 27, 2021

(this may be a feature, but I find it counter-intuitive)

@alexcjohnson
Copy link
Collaborator

That would be a bug but I can't reproduce the behavior you're describing. In fact, if I try to NOT wrap the output in a list, Dash correctly throws an error.

The one funny thing I notice here is it seems dbc.Select always returns a string for its value prop, even if you provide a number or bool. And since that conversion happens on the JS side, Python's True turns into "true". That may be worth discussing in https://github.com/facultyai/dash-bootstrap-components. The dash_core_components equivalent dcc.Dropdown doesn't support bools (see plotly/dash-core-components#957) but it does preserve numbers.

So here's my update of your toy app that appears to work as you intended:

import dash
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc
import dash_html_components as html

app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

app.layout = html.Div(
    children=[
        dbc.Modal("hi", id="modal"),
        dbc.Select(id="select", options=[{"label": "T", "value": True}, {"label": "F", "value": False}])
    ]
)

@app.callback([Output("modal", "is_open")], [Input("select", "value")])
def toggle_modal(b):
    return [b == "true"]

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

@JonThom
Copy link
Author

JonThom commented May 15, 2021

Hi @alexcjohnson,
Thank you so much for looking into this and apologies for jumping to the wrong conclusion about the cause of the unexpected behaviour.

@JonThom JonThom closed this as completed May 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants