How can I enable and disable a tab with callbacks?

How would you enable a tab by using callouts? As an example below, I have two tabs where the second one ‘tab-2’ is disabled.

from dash import Dash, DiskcacheManager, CeleryManager, dcc, html,no_update, ctx, dash_table
from dash.dependencies import Input, Output, State

app.layout = html.Div([

    dcc.Tabs(id="tabs-styled-with-inline", parent_className='custom-tabs',value='tab-1', children=[
        dcc.Tab(label='Class Stats', 
            value='tab-1', 
            style=tab_style, 
            selected_style=tab_selected_style, 
            disabled=False,
            children=[something_layout]),
        dcc.Tab(label='Class Analysis', 
            value='tab-2', 
            style=tab_style, 
            selected_style=tab_selected_style, 
            disabled=True,
            children=[something_layout2]),
    ], colors={
        "background": "#434343"
    },style=tabs_styles),
    html.Div(id='tabs-content-inline'),
    dcc.Store(id='current-data'),
    ],
)

I thought it would be something like this below:

@app.callback(
    Output("tab-2", "disabled"),
    Input('current-data', 'data'),
)
def enable_tab(current_df):
    return False

But I am not getting anywhere with it. I believe it has to do something with the tabs ID being “tabs-styled-with-inline” and I have to maybe specify that the tab-2 is part of that ID. Could someone show me how this works?

For clarification, the enable_tab function should be triggered whenever the current-data gets populated or refreshed…I’ve added it as a dcc.Store element in the example above.

Hi @jarelan ,

your logic works as expected, I added ID’s to the two dcc.Tabs() and a button to the first tab layout in order to update the dcc.Store(). I also added prevent_initial_call=True so that the first callback does not get triggered at startup.

from dash import Dash, DiskcacheManager, CeleryManager, dcc, html, no_update, ctx, dash_table
from dash.dependencies import Input, Output, State

app = Dash()
app.layout = html.Div([

    dcc.Tabs(
        id="tabs-styled-with-inline",
        parent_className='custom-tabs',
        value='tab-1',
        children=[
            dcc.Tab(
                label='Class Stats',
                value='tab-1',
                id='tab-1',
                # style=tab_style,
                # selected_style=tab_selected_style,
                disabled=False,
                children=[
                    html.Button(
                        'enable',
                        id='btn'
                    )
                ]
            ),
            dcc.Tab(
                label='Class Analysis',
                value='tab-2',
                id='tab-2',
                # style=tab_style,
                # selected_style=tab_selected_style,
                disabled=True,
                children=[html.Div('empty')]),
        ], colors={
            "background": "#434343"
        },
        # style=tabs_styles
    ),
    html.Div(id='tabs-content-inline'),
    dcc.Store(id='current-data'),
],
)


@app.callback(
    Output("tab-2", "disabled"),
    Input('current-data', 'data'),
    prevent_initial_call=True
)
def enable_tab(current_df):
    return False


@app.callback(
    Output('current-data', 'data'),
    Input('btn', 'n_clicks'),
    prevent_initial_call=True
)
def change_state(n_clicks):
    return n_clicks


if __name__ == "__main__":
    app.run(debug=True, threaded=True, port=8080)
3 Likes

and the initial call was what kept the tab from enabling?

The id would be the key thing you were missing there. The callback looks for the ID so I knows what it’s suppose to be triggering.

AIMPED added in to the tabs

id='tab-1'

and

id='tab-2'

And those will tie into the callback you already created

@app.callback(
    Output("tab-2", "disabled"),
    Input('current-data', 'data'),
)
def enable_tab(current_df):
    return False

The prevent_initial_call=True is used to stop the callback from trying to fire when you first run the application.

2 Likes

H @jarelan,

thanks @payton-dev for the explication. The missing ID were the main thing. Actually your code should have thrown a error at statrup.

The prevent_initial_callback=True was necessary because if you do not prevent this callback at startup, the callback gets triggered and your tab is never disabled as the value is set to False. You will see the difference if you comment out this line.

1 Like

Thank you so much for your help!!!

1 Like