Black Lives Matter. Please consider donating to Black Girls Code today.

Using buttons as tabs

Hi there,

I’m trying to create a basic multi-tabbed app framework/callback using buttons (not using dcc.Tabs). Below is the code:

import dash
import dash_core_components as dcc
import dash_html_components as html

app = dash.Dash(__name__)

app.layout = html.Div([
    html.Button('tab1', id='tab1', n_clicks=0),
    html.Button('tab2', id='tab2', n_clicks=0),
    html.Button('tab3', id='tab3', n_clicks=0),

    html.Div(id='content')
])

@app.callback(
    dash.dependencies.Output('content','children'),
    [dash.dependencies.Input('tab1', 'n_clicks' ),
    dash.dependencies.Input('tab2', 'n_clicks' ),
    dash.dependencies.Input('tab3', 'n_clicks' )]
)

def on_click(one,two,three):
    if one:
        return html.H1(one)
    elif two:
        return html.H1(two)
    elif three:
        return html.H1(three)
    else:
        return html.H1("Select a tab")

if __name__ == '__main__':
    app.run_server(debug=True)

The expected behavior is that clicking different tabs will serve different content (an h1 that displays the number of times a particular tab has been clicked). It will update when clicking a higher tab to a lower tab (i.e. if I click ‘tab3’ a bunch of time and then click ‘tab2’ or ‘tab1’ it will update), but it won’t update if I click a higher tab (i.e. if I first click ‘tab1’ and then click ‘tab2’, the change will not be made/the H1 won’t update, i.e. it will continue to show 'tab1’s count forevermore).

Not sure why this is. Any help would be much appreciated. Obviously the point here ultimately is to call different pages of content based on which has been selected.

Thanks in advance.

n_clicks just tells you how many times each button was clicked. So, when you’ve clicked each button a few times, you’ll have, for example, one=4,two=10,three=8`.

What you’ll need is to determine which button was clicked. You can do that with the n_clicks_timestamp property, see Input two or more button - How to tell which button is pressed?

So the trick seems to be:

if one>two and one>three: in the callback definition.

I still don’t understand why the conditional is required in the first place (i.e. if button2 is clicked, shouldn’t the elif two: be satisfied?), but tis’ working as intended with the conditionals so I’ll go ahead and consider this resolved.

Thanks,
David

Just for completeness here is the working version.

import dash
import dash_core_components as dcc
import dash_html_components as html

app = dash.Dash(__name__)

app.layout = html.Div([
    html.Button('tab1', id='tab1', n_clicks_timestamp=0),
    html.Button('tab2', id='tab2', n_clicks_timestamp=0),
    html.Button('tab3', id='tab3', n_clicks_timestamp=0),

    html.Div(id='content')
])

@app.callback(
    dash.dependencies.Output('content','children'),
    [dash.dependencies.Input('tab1', 'n_clicks_timestamp' ),
    dash.dependencies.Input('tab2', 'n_clicks_timestamp' ),
    dash.dependencies.Input('tab3', 'n_clicks_timestamp' )]
)

def on_click(one,two,three):
    if one>two and one>three:
        return html.H1("This is tab 1")
    elif two>one and two>three:
        return html.H1("This is tab 2")
    elif three>two and three>one:
        return html.H1("This is tab 3")
    else:
        return html.H1("Select a tab")

if __name__ == '__main__':
    app.run_server(debug=True)

working