How to update component when button is clicked

First and foremost, I have already previewed this post: [html.Button - Adding a click event](http://html.Button - Adding a click event)

My issue though stems from not needing the n_clicks values, but simply the acknowledgement that a button was pressed. I’m trying to create a button that resets all dropdowns to their default values when clicked. Not sure how this can be done with n_clicks though. Any suggestions?

Thanks!

1 Like

If n_clicks changes, then that tells you that the button was clicked. You’re free to ignore the actual value in your callback.

Though you may want to catch n_clicks==0 because that callback will happen when the page first loads.

1 Like

If n_clicks changes

Forgive me if this is a silly question, but how would I be able to check this?

Thanks.

The callback function will only be called when one of the inputs changes (and on initial page load).

That wont work for my case: I have an output that can be changed based off inputs, but if the button is pressed, the output should be reset the default component.

To better illustrate:

@app.callback(
    Output('dropdown-a', 'options'),
    [Input('dropdown-b', value'),
     Input('dropdown-c', value)])

The idea here is that I’m creating dependant drop downs that change based on the other dropdown choices. Now since I can’t have more than one callback on a single output component, then I would have to do some type of logic statement that produces a different return value. Here is something I thought of, but not sure how to implement. Let me know what your thoughts are.

 @app.callback(
        Output('dropdown-a', 'options'),
        [Input('dropdown-b', value'),
         Input('dropdown-c', 'value'),
         State('button', ;n_clicks')])
def update_dependant_d(....):
    if (n_clicks changed):
         return default_options
    else: 
         return dependant_dropdown

Right now you it’s not possible to tell which component has changed, you can only get the current state of all of the components that the callbacks depend on.

Ah yeah. As @chriddyp says it’s not possible to figure out which of the inputs has changed.

It seems to me like your case might be doable though. Can you set dropdown-a options based just on the b and c values?

e.g.

@app.callback(
    Output('dropdown-a', 'options'),
    [Input('dropdown-b', value'),
     Input('dropdown-c', value)])
def set_a_options(b,c):
    if b=='default' or c=='default':
        get_a_default()
    else:
        do_something_else(b,c)

@app.callback(
        Output('dropdown-b', 'value'),
        [Input('button', 'n_clicks')])
def update_b_to_default(n):
    return 'default'
1 Like

That is a good suggestion, but my issue is that dropdown b is also dependent on other dropdown inputs, I couldn’t just add the button as the only input.

i.e.

@app.callback(
    Output('dropdown-b', 'options'),
    [Input('dropdown-a', value'),
     Input('dropdown-c', value)])
    def set_b_options(a, c): ....

There has to be some way to return everything to the initial state?

@chriddyp, is there any possible way to bypass the restriction of having only one output callback per component? That would also solve this issue.

Those are the dropdown-b options though right? Is the value really dependent on other dropdown inputs as well? (if so, should it really even be a dropdown?)

Yes, they are all connected.

Each dropdown corresponds to a column in the table and is used to filter that dataframe. Take the example below. If Americas is chosen in dropdown A, than dropdown b should only show USA, Canada as options and only Switzerland and Germany for dropdown c.
Or another example: if Germany is chosen from dropdown b, than dropdown a’s options should only be EMEA and dropdown c’s options should only show USA and Japan.

The purpose of this is to improve UI by removing options from the dropdowns that will not have any data based on the filter created.

image

It seems to me that the example I posted a little ways up should work fine for this example (except I confused what was A, B, and C). So something like this:

@app.callback(
    Output('dropdown-b', 'options'),
    [Input('dropdown-a', value')])
def set_b_options(a_val):
    return get_countries_in_region(a_val)

@app.callback(
    Output('dropdown-c', 'options'),
    [Input('dropdown-a', value')])
def set_c_options(a_val):
    return get_countries_not_in_region(a_val)

@app.callback(
        Output('dropdown-a', 'value'),
        [Input('button', 'n_clicks')])
def update_a_to_default(n):
    return 'America' #or whatever default

There isn’t anyway to get around this right now besides writing this Dash feature into dash’s backend and front-end (or contracting Plotly to build this feature out)

Hello, I am having the same issue. I was wondering if you’ve found a solution to it?

@rkahhale I actually ended up writing this app in vanilla javascript. While dash is an amazing library for building visualizations, it ended up not being the simplest solution for this particular project.

That said, I’d still be happy to help you with your issue. Do you mind opening a new thread though? Tag me in it.

I faced the same issue and the solution that I found out is to set the button as ‘Input’ and the other inputs as ‘State’. Then the callback will only be launched when the button is clicked and not when the other inputs are changed.

1 Like

I had a similar problem. I have several html and dcc components which are all used to update one graph. I wanted to use a button for exporting the graph using plotly.offline. The solution I found for determining whether or not the button is the last activated component, is comparing the n_click_timestamp to the current timestamp, i.e.: (pseudo-code)

if n_clicks_timestamp > (datetime.datetime.now().timestamp.()-1 second):
Export graph
I hope this helps

Another solution is adding a global variable to track the number of clicks. Then you can check in callback if the new n_clicks is larger.

Is there a recommended way to only perform an associated action with a button click once?

Right now I use something like :

if n_clicks ==1:
    do something

and I set up my button in the callback like :
Input("button", "n_clicks"),

I think this post is pretty similar to this thread: Which component triggered the callback

Its an effective way to figure out what button or any other component has changed, and update another component based on which one was triggered. It uses hidden divs to store the timestamps of when each component was called, and compares to the current time to figure out which one was called last - similar to nahal626 and Harold’s suggestions. This referenced link may be useful since its all written out.

I’d say that’s the way to do it (as you’ve written out).