1

How can I write a callback such that if button 1 is clicked, do A; if button 2 is clicked, do B; if a dropdown value is changed, do C?

import dash
import dash_core_components as dcc
import dash_html_components as html

app = dash.Dash(__name__)
app.layout = html.Div([
        html.H1('initial', id = 'h1'),
        html.Button('to upper', id = 'upper button', n_clicks_timestamp = '0'),
        html.Button('to lower', id = 'lower button', n_clicks_timestamp = '0'),
        dcc.Dropdown(options = [{'value':s, 'label': s} for s in ['good','bad']], value = 'good', id = 'set string')
    ])

@app.callback(
         dash.dependencies.Output('h1', 'children'),
         [dash.dependencies.Input('upper button', 'n_clicks_timestamp'), 
          dash.dependencies.Input('lower button', 'n_clicks_timestamp'), 
          dash.dependencies.Input('set string', 'value')],
         [dash.dependencies.State('h1', 'children')]
    )
def update(upper, lower, newstring, currentstring):
    upper, lower = int(upper), int(lower)

    # ???
    # if dropdown changed, return newstring
    # ???

    if upper > lower:
        return currentstring.upper()
    if lower > upper:
        return currentstring.lower()

    return newstring

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

Since the dropdown doesn't have a timestamp property, there is no way to decide if it is the latest change.

1 Answer 1

1

Do the buttons get to be pressed multiple times in your callback? If not, when the callback is triggered by the dropdown, the buttons will have 0 as n_clicks and None (or also 0, I don't recall) as n_clicks_timestamp. So you can infer that the dropdown triggered the callback, by process of elimination.

If the buttons get to be pressed multiple times, you need to create another callback on the children property of a Div containing the buttons, and simply re-instantiate the buttons, so that they will still be at 0 n_clicks and timestamp for the next callback.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks. Not sure what you mean by re-instantiate the buttons. Can you set the button's property when your output is something else?
You can have multiple callbacks with the same input. I am saying you have a callback on the children property of the container of the buttons and if the button timestamp is not None you just re-render the buttons by returning them in the callback. Otherwise you just raise PreventUpdate on that second callback.
I understand now. Thanks.
@giobatta912 some example code here would be beneficial (for newbies like me) :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.