How to fire html.Button on page load? I.e. have a default active button

Hi there,

On my dash app I have 3 buttons and I want to set one of them to be the default active pressed button upon page load. So when I load up my app, this one button should look like it’s already been pressed.

Looking at other somewhat similar examples, I still haven’t been able to find the solution for my case. As I understand, if n_clicks=0 or n_clicks=None then it should fire on page load? I have tried both, setting n_clicks to 0 and None (the latter of which is shown below). I also tried using dbc.Button instead and using the active=True property as well, but so far with no results.

From my code, I want to set my “Overview” button to be the active pressed button when I first load up.

Would appreciate any help on this. Thank you.

Button code:

    # Buttons
    html.Div([
        html.Button('Overview', id='button_overview', n_clicks=None),
        html.Button('Details', id='button_details', n_clicks=1),
        html.Button('Employee Data', id='button_employee_data', n_clicks=1),
        html.Div(id='page')
    ]),

Callback code:

# Callback - buttons
@app.callback(Output('page', 'children'),
              Input('button_overview', 'n_clicks'),
              Input('button_details', 'n_clicks'),
              Input('button_employee_data', 'n_clicks'))
def render_page(button_1, button_2, button_3):
    changed_id = [p['prop_id'] for p in dash.callback_context.triggered][0]
    
    if 'button_overview' in changed_id:
        return html.Div([
            dcc.Markdown('''Overview coming soon''')
        ])
    
    elif 'button_details' in changed_id:
        return html.Div([
            html.Br(),
            dcc.Markdown('''**Select filters**'''),
            dcc.Markdown('''Category'''),
    
            # Radio buttons for graph category
            dcc.RadioItems(
                id='graph_category',
                options=[
                    {'label':'Department', 'value':'Department'}, 
                    {'label':'Position Level', 'value':'Position Level'},      
                ],
                value='Department',
                labelStyle={'display':'inline-block'},
                inputStyle={'margin-left':'30px'}
            ),
            
            html.Br(),
            
            # Markdown text
            dcc.Markdown('''Departments'''),
            
            # Checklist row
            html.Div([
                # Checklist - all departments
                    dcc.Checklist(
                    id='checklist_all_dept',
                    options=[{'label': 'All', 'value': 'All'}],
                    value=['All'],
                    labelStyle={'display': 'inline-block'},
                    inputStyle={'margin-left':'30px'},
                ),
            ], style={'display':'inline-block'}),

            html.Div([
                # Checklist - departments
                dcc.Checklist(
                    id='checklist_dept',
                    options=options,
                    value=[],
                    labelStyle={'display': 'inline-block'},
                    inputStyle={'margin-left':'30px'},
                ),        
            ], style={'display':'inline-block'}),
            
            
            dbc.Card([
                html.Div([
                    dcc.Graph(id='graph1'),
                    dcc.Graph(id='graph2')
                ], style={'columnCount':2}),
            ], color='primary'),
        ])
    
    elif 'button_employee_data' in changed_id:
        return html.Div([
            dash_table.DataTable(
                id='table',
                columns=[{'id':c, 'name':c} for c in df.columns],
                data=df.to_dict('records'),
                page_size=20,
                style_table={'height':'500px', 'overflowY':'auto'}
            )
        ])

EDIT: Full callback code included

@grvlagrv

Show the rest of your callback to try to find the problem. :thinking:

Thanks Eduardo, I’ve edited to include. Also pasting here as well:

# Callback - buttons
@app.callback(Output('page', 'children'),
              Input('button_overview', 'n_clicks'),
              Input('button_details', 'n_clicks'),
              Input('button_employee_data', 'n_clicks'))
def render_page(button_1, button_2, button_3):
    changed_id = [p['prop_id'] for p in dash.callback_context.triggered][0]
    
    if 'button_overview' in changed_id:
        return html.Div([
            dcc.Markdown('''Overview coming soon''')
        ])
    
    elif 'button_details' in changed_id:
        return html.Div([
            html.Br(),
            dcc.Markdown('''**Select filters**'''),
            dcc.Markdown('''Category'''),
    
            # Radio buttons for graph category
            dcc.RadioItems(
                id='graph_category',
                options=[
                    {'label':'Department', 'value':'Department'}, 
                    {'label':'Position Level', 'value':'Position Level'},      
                ],
                value='Department',
                labelStyle={'display':'inline-block'},
                inputStyle={'margin-left':'30px'}
            ),
            
            html.Br(),
            
            # Markdown text
            dcc.Markdown('''Departments'''),
            
            # Checklist row
            html.Div([
                # Checklist - all departments
                    dcc.Checklist(
                    id='checklist_all_dept',
                    options=[{'label': 'All', 'value': 'All'}],
                    value=['All'],
                    labelStyle={'display': 'inline-block'},
                    inputStyle={'margin-left':'30px'},
                ),
            ], style={'display':'inline-block'}),

            html.Div([
                # Checklist - departments
                dcc.Checklist(
                    id='checklist_dept',
                    options=options,
                    value=[],
                    labelStyle={'display': 'inline-block'},
                    inputStyle={'margin-left':'30px'},
                ),        
            ], style={'display':'inline-block'}),
            
            
            dbc.Card([
                html.Div([
                    dcc.Graph(id='graph1'),
                    dcc.Graph(id='graph2')
                ], style={'columnCount':2}),
            ], color='primary'),
        ])
    
    elif 'button_employee_data' in changed_id:
        return html.Div([
            dash_table.DataTable(
                id='table',
                columns=[{'id':c, 'name':c} for c in df.columns],
                data=df.to_dict('records'),
                page_size=20,
                style_table={'height':'500px', 'overflowY':'auto'}
            )
        ])

Hey @grvlagrv

Dash fires all the callbacks the first time is executed, but in your case, you are asking in the callback what is the button that has been executed and not what value each n_clicks has.

So no button is executed when the app is loaded, thats why the callback do not return the desired option.

You have to add an if row at the first of the callback asking for the value of the n_clicks component of the button that you want to be fired:

def render_page(button_1, button_2, button_3):

    if button_1 == 0:
        return html.Div([dcc.Markdown('''Overview coming soon''')])
    
    
    changed_id = [p['prop_id'] for p in dash.callback_context.triggered][0]

:grinning:

THANK YOU. Evidently I’ve been misunderstanding this. So then if I may ask another question, is there a way I can set this to equal the same output as when I actually click on the “Overview” button? There are 2 other buttons so if the user clicks back to the “Overview” button, it would have the same output except however currently the only way I can think to do this is to duplicate the output (copy and paste the same code for both if statements).

I tried the below but it didn’t work (and it cancelled out the functionality of the line that you added for me). As an extension of that line that you added, I’m trying to use the logic “if button_1 equals 0 or the overview button”. I know this sounds funky since button 1 would be the overview button, but I’m having trouble refining this logic. I hope you can follow what I mean :P. Essentially, when the app loads and automatically displays the contents from button 1, I am intending for it to be like it’s actually pressed as in the line “if ‘button_overview’ in changed_id:”.

Is it possible for me to have these equal the same so I don’t have to copy and paste the same code for both if statements?

def render_page(button_1, button_2, button_3):
    
    if button_1 == 0 | button_1 == 'button_overview':
        return html.Div([dcc.Markdown('''Overview coming soon''')])
    
    changed_id = [p['prop_id'] for p in dash.callback_context.triggered][0]

I’m not sure if I understand your question :woozy_face:

If you just add the line I added and remains all the code as you had, when the users clics the first button it will fired again because of the second part of the callback that ask if the id of that button was clicked.

That means that there are two if conditions with the same return.

If you want to avoid two if statements, the condition you need must be place after the variable that gets the id of the clicked button and this or condition has to reference the id clicked instead of the button:


def render_page(button_1, button_2, button_3):

    changed_id = [p['prop_id'] for p in dash.callback_context.triggered][0]

    if button_1 == 0 | 'button_overview' in changed_id:
        return html.Div([dcc.Markdown('''Overview coming soon''')])
    
    
   

Thank you Eduardo, that makes perfect sense and the code you suggested is exactly what I was aiming for :). Unfortunately the code didn’t work as it had produced a callback error of sorts. But that’s okay. At this point I think I will just go back to using dcc.Tabs objects instead. My preference is for buttons but honestly I think I’m ready to throw in the towel on this one. But thank you very much for your feedback and help!

1 Like