Mr.Slow
Mr.Slow

Reputation: 560

Incorrect function of 2 chained buttons in Dash app

Having the dash app layout example allows me to export 2 DataTables in Excel. First, it requires an excipient value submitted by pressing a "Submit" button, then it is possible to use the "Export" button. All working great. However, if I change the excipient value after I already exported the tables (aka fired the Export button), the datatables are downloaded with firing the "Submit" button! Meaning that in a 2nd cycle of using the Dash app, the Submit button works as Export button, too, which is wrong. How can that be handled? I tried to implement the app.clientside_callback as shown here: Plotly Dash: Download getting triggered automatically after removing element but without success since it should work only in single callback scope. Thank you for suggestions.

import dash
from dash import Dash, html, dcc, dash_table
from dash.dependencies import Input, Output, State
from dash import dash_table 


# simplified Dash app. layout:
app.layout = html.Div([
    html.Div([
        html.H1("CLUSTER ANALYSIS"),
        html.H2("Enter 1 or multiple values, then press 'Submit'.",
               style = {'color': 'black', 'fontSize': 17}),
        dcc.Input(id = 'excipient',type = 'text') 
        html.Br(),
        html.Button(id = "submit-button", n_clicks = 0, children = 'Submit'),
    ]),
    
    html.Br(),
    
    html.Div([dcc.Graph(figure1]),
    
    
   html.Div([
        html.Div([table1]),
        html.Br(),
   ]),
    html.Div([
        html.Button(id = "export-button", children = 'Export'),
        html.Br(),
    ]),
    
    html.Div([
        dcc.Download(id = 'download_component'),
    ]),
    html.Div([
        html.Div([table2]),
       ]),
    ])

@app.callback(
    Output('figure1', 'figure'),
    Output("table1", "data"),
    Output("table2", "data"),
    Input('submit-button', 'n_clicks'),
    Input('table1', 'selected_rows'),
    State('excipient', 'value'),
    prevent_initial_call = True)

def update_function(n_clicks, selected_rows, excipient)
      # updates tables



@app.callback(
    Output('download_component', "data"),
    Input('export-button', 'n_clicks'),
    Input("table1", "data"),
    Input("table2", "data"),
    prevent_initial_call = True)

def export_function(n_clicks, data1, data2):
      # saves tables as .xlsx

Upvotes: 0

Views: 74

Answers (1)

coralvanda
coralvanda

Reputation: 6616

You haven't shared the logic for your export_function callback, but I bet you have something like this:

if n_clicks:
   # perform download action

What happens is, because your data inputs are causing this callback to fire, the n_clicks value is always truthy after the first run, so it always downloads.

The fix is to make your data inputs State and not Input, so that the callback only fires when the user clicks the button to download.

Upvotes: 1

Related Questions