How do I appropriately use an html.Button?


[Edit: I think I can use state to fix this!]

Hi experts,

My app includes two datepicker and one dropdown to generate a parameter tuple and a button to query a table valued function in a SQL Server with that parameter tuple.

However I’m kind of lost of how to write the callback of the button.

You see, I can do this in two ways:

  1. I can setup the callback with Input from the button,the datepickers and the dropdown. In the function I’ll assembly the list and do the query. This removes the need for writing callbacks for the datepickers and the dropdown, but has a serious problem: This callback is called whenever any of the Input changes. For example I can just pick another date and the query starts anew. Here is the code:

    dash.dependencies.Input(‘startquery’, ‘n_clicks’), # this is the button
    dash.dependencies.Input(‘network-input’, ‘value’), # dropdown
    dash.dependencies.Input(‘startdate-input’, ‘date’), # datepicker 1
    dash.dependencies.Input(‘enddate-input’, ‘date’) # datepicker 2
    def start_query(n_clicks, networkid, startdate, enddate):
    if n_clicks is not None:
    query_params = (startdate[:10], enddate[:10], 7, networkid)
    conn_str = ‘DRIVER={SQL Server};SERVER=reporting-sql;DATABASE=MyDB;Trusted_Connection=yes’
    cnxn = pyodbc.connect(conn_str)
    cursor = cnxn.cursor()
    cursor.execute(""“SELECT * FROM fn_MyFunc(?, ?, ?, ?)”"", query_params)
    df_result = pd.DataFrame.from_records(cursor.fetchall())
    return df_result[:10].to_dict(“rows”)

  2. I can also write a separate callback for all three “parameter widgets”. I’ll output it to a hidden div and use this hidden div as part of input for the button. For this I need to use a list instead of a tuple. However this still poses the same issue: Whenever the parameter is updated, it automatically “clicks” the button. So for now I’m not using an intermediate element but falling back to using nonlocal to modify variables.

I’m wondering if I should NOT use n_clicks but something else for the button callback?


OK solved! It’s very easy, just use state instead of input for those widgets that you do not want to “trigger” the callback.