How to update component when button is clicked


#1

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!


#2

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.


#3

If n_clicks changes

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

Thanks.


#4

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


#5

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

#6

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.


#7

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'

#8

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.


#9

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?)


#10

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


#11

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

#12

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)


#13

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


#14

@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.


#15

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.


Using Button n_clicks property to trigger per each click
#16

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