Nick9214
Nick9214

Reputation: 37

Dash - Callback with 2 input

I have 2 dropdown list and one text area. I need the text area to accept input from both drop-down lists indiscriminately (one at a time, according to which the user select), but display only the last value selected (evry time i select a value from one of the two dropdown, it overwrite the last one selected).

How do I write the callback?

I thought I could simply write:

@app.callback(
Output(component_id='text_output', component_property='value'),
Input(component_id='lista_file_mt', component_property='value'),
Input(component_id='lista_file_crt', component_property='value'))

But, obviously, it doesn't work

Upvotes: 1

Views: 1228

Answers (1)

John Collins
John Collins

Reputation: 2951

Dynamic text output concatenates multi=True dropdown options

Something like this?:

import dash

from dash import dcc
from dash import html
from dash import no_update
from dash.dependencies import Input
from dash.dependencies import Output


app = dash.Dash(__name__)

app.layout = html.Div(
    [
        dcc.Dropdown(
            id="dropdown-1",
            options=[
                {"label": "a", "value": "a"},
                {"label": "b", "value": "b"},
                {"label": "c", "value": "c"},
            ],
            multi=True,
        ),
        dcc.Dropdown(
            id="dropdown-2",
            options=[
                {"label": "d", "value": "d"},
                {"label": "e", "value": "e"},
                {"label": "f", "value": "f"},
            ],
            multi=True,
        ),
        html.Div(id="textarea-1", children=[]),
    ]
)


@app.callback(
    Output("textarea-1", "children"),
    [Input("dropdown-1", "value"), Input("dropdown-2", "value")],
    prevent_initial_call=True,
)
def update_text_input(dd1, dd2):
    text = []
    if dd1:
        text += ["".join(dd1)]
    if dd2:
        text += ["".join(dd2)]
    return text


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

example of app

Dynamic text outputs only single value indiscriminately from any present dropdowns

Alright, this is a tiny bit more complex, requiring the use of dcc.Store, to be able to discern when a dropdown has been changed, which one is it which has a new value that differs from the value currently already [last] displayed.

import sys

import dash
from dash import html
from dash import dcc
from dash import no_update
from dash.dependencies import Input, Output, State


app = dash.Dash(__name__)

app.layout = html.Div(
    [
        dcc.Store(id="session", storage_type="session"),
        dcc.Dropdown(
            id="dropdown-1",
            options=[
                {"label": "a", "value": "a"},
                {"label": "b", "value": "b"},
                {"label": "c", "value": "c"},
            ],
            placeholder="Choose a value",
            value=None,
        ),
        dcc.Dropdown(
            id="dropdown-2",
            options=[
                {"label": "d", "value": "d"},
                {"label": "e", "value": "e"},
                {"label": "f", "value": "f"},
            ],
            placeholder="Choose a value",
            value=None,
        ),
        html.Div(id="textarea-1", children=[]),
    ]
)


@app.callback(
    [Output("textarea-1", "children"), Output("session", "data")],
    [Input("dropdown-1", "value"), Input("dropdown-2", "value")],
    State("session", "data"),
    # prevent_initial_call=True,
)
def update_text_input(dd1, dd2, data):
    print(dd1, dd2, data, file=sys.stderr)
    if not data:
        print(dd1, dd2, data, file=sys.stderr)
        return no_update, {"dd1": None, "dd2": None}
    if dd1 and (dd1 != data["dd1"]):
        return [dd1], {"dd1": dd1, "dd2": data["dd2"]}
    if dd2 and (dd2 != data["dd2"]):
        return [dd2], {"dd1": data["dd1"], "dd2": dd2}

    return no_update, data


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

app knows which latest dropdown to display-1 app knows which latest dropdown to display-2

Upvotes: 1

Related Questions