Callback function of button is called automatically

I am using the similar button callback code as mentioned in the dash guide. But the problem I am facing is that the callback function is called automatically at the start , even when the button is not pressed. I need that function should only be called when the button is pressed.

Check if n_clicks==None and then raise dash.exceptions.PreventUpdate()

Callbacks will always be fired at the start to keep everything consistent

1 Like

Hi @chriddyp , how to stop the button keeping running? Once you click the button, the value won’t be None any more, I experience the callback feature based on the button keeps running again and again? Do we need to reset the n_clicks = 0 in the end of the callback function? I tried that too but it didn’t work. Any advice?

The callbacks should only run “again and again” if you click the button again and again. Resetting n_clicks = 0 is usually not needed. Please share your code and elaborate the problem in detail.

Hi @MichelH , below is my callback function. when i am in the DataTable, it keeps adding the rows when I tabbed to next column to fill in values, and I didn’t keep clicking that add_row button.

def add_update_row(add_row_clicks, timestamp, rows, columns):
    if add_row_clicks is None:
        raise PreventUpdate
    elif add_row_clicks > 0:
        rows.append({c['id']: np.nan for c in columns})
        
        # Updating click to zero to avoid keep-running: --> btw, this isn't working.
        add_row_clicks = 0

    return rows

Please also provide the decorator of your callback (i.e. the part that says @app.callback(...) before the function).

Indeed setting add_row_clicks = 0 as you do in your function will not have any effect, as you are not returning that value, thus not actually setting the property of the button.

I suspect that it’s not actually the button that causes your callback to fire, but some other Input (can’t tell for sure without seeing the @app.callback part). You just didn’t see it firing before because add_row_clicks was still None, so it aborted right away. To test this hypothesis, you could print which component caused the callback to fire by adding this line to your function:
print(dash.callback_context.triggered)

Hi @MichelH - thanks for your kind help.

The decorator is per below:

@app.callback(
    Output('xxx-matrix-inputs', 'data'),
    Input('add-rows-button', 'n_clicks'),
    Input('xxx-matrix-inputs', 'data_timestamp'),
    State('xxx-matrix-inputs', 'data'),
    State('xxx-matrix-inputs', 'columns')
    )

I just now added that line to test and it gave me two print results - any idea?

[{'prop_id': 'add-rows-button.n_clicks', 'value': 1}]

[{'prop_id': 'xxx-matrix-inputs.data_timestamp', 'value': 1628157032263}]

Hi @MichelH - I have another question in this post, wondering if you know anything? Much appreciated!

Well, the second print shows that the seconds firing of the callback was not fired by the button, but by Input('xxx-matrix-inputs', 'data_timestamp'). This makes sense: The callback is triggered, it edits the data, which in turn updates data_timestamp, which fires the callback again and so on.

If you only want your callback to fire when the button is clicked, make the button click the only input (i.e. make 'xxx-matrix-inputs', 'data_timestamp' a State).

HI @MichelH : you brilliant! That is working perfectly now! Thank you so much!!