Dropdown callback is called on tab change

Hello community! I have a multi tab page where i create the tabs dynamically:

def layout():
return html.Div([
        html.Div(id='hidden-div', style={'display':'none'}),
        dcc.Location(id='s_url', refresh=False),
        html.Div(
            dcc.Tabs(id='s_tabs',
                     vertical=True,
                     style={'height': '60vh',
                            'borderRight': 'thin lightgrey solid',
                            'textAlign': 'left'}),
            style={'width': '15%', 'float': 'left'}
        ),
        html.Div(
            html.Div(id='s_tab_output'),
            style={'width': '85%', 'float': 'right'}
        )
    ], style={
        'margin-left': 'auto',
        'margin-right': 'auto',
    })    

and i populate the tabs in a callback:

@dashapp.callback(
        [Output('s_tab_output', 'children'),
         Output('s_tabs', 'children')], 
        [Input('s_tabs', 'value')]
    )
    def render_tab(active_tab):
        tab_list = []
        for app in current_user.preferences.keys():
            tab_list.append(dcc.Tab(label = app.capitalize(), 
                                    value = app))
        
        if active_tab == 'tab1':
            tab_pane = _render_tab1()
        elif active_tab == 'tab2':
            tab_pane = _render_tab2()
        
        return tab_pane, tab_list

   def _render_tab1():
       my_list = ['a', 'b', 'c']
       return html.Div([
            html.Div(['Header'], style={'display': 'inline-block', 'verticalAlign': 'bottom', 'width': '10%'}),
            html.Div(['Some Text'], style={'display': 'inline-block', 'verticalAlign': 'bottom', 'width': '10%'}),
            html.Div([dcc.Dropdown(id={'type': 'dropdown', 'index': 'chart_1_dd'},
                                   searchable=True,
                                   options=[{'label': x,
                                             'value': x} for x in my_list],
                                   value=my_list[0])], 
                      style={'display': 'inline-block', 'verticalAlign': 'bottom', 'width': '20%'})])

what im trying to capture is when chart_1_dd changes value, so i set up a callback:

@dashapp.callback(
        Output({'type': 'dropdown', 'index': MATCH}, 'value'),
        Input({'type': 'dropdown', 'index': MATCH}, 'value'),
        [State({'type': 'dropdown', 'index': MATCH}, 'id'),
         State('s_tabs', 'value')],
        prevent_initial_update=True)
    def dropdown_changed(dd_value, dd_id, active_tab):
        print(dd_value)
        print(dd_id)
        print(active_tab)
        return dd_value

now my questions are two fold:

  1. when the page loads, no tabs are active and I’d like to set the first tab in tab_list, but i cant seem to figure that out
  2. when tabs are selected (going from one to the next) the dropdown_changed() callback is always fired, even if the dropdown itself didn’t change (it was simply a tab refresh). why is that the case? I’d like the callback to be triggered only if the dropdown itself is actually changed.
  3. prevent_initial_update doesn’t seem to work in this context.
    thanks-

I have an answer for your first question: Set the “value” property of dcc.Tabs to your desired initial tab. If you know the value of the dcc.Tab you want to set as default, hardcode it directly in your layout. If it’s dynamic, add it as an Output of your render_tab callback, e.g. Ouput('s_tabs', 'value')

An example of the first solution (hardcoded) can be found in the docs (see Method 1): Tabs | Dash for Python Documentation | Plotly

great thank you, one down, 2 to go!