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

Problem with the new Tabs

I’m having an issue: when I select a tab for the first time, the layout is correct , but when I switch tabs and then return to it, the layout has been messed up. When I use the previous versions of dash_core_components this problem doesn’t happen. The problem is illustrated below:

Here is the example code:

import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objs as go

df = pd.read_csv(
    'https://raw.githubusercontent.com/plotly/'
    'datasets/master/gapminderDataFiveYear.csv')

app = dash.Dash()

div1=html.Div([ html.Div([
                dcc.Graph(id='graph-with-slider'),
                dcc.Slider(
                    id='year-slider',
                    min=df['year'].min(),
                    max=df['year'].max(),
                    value=df['year'].min(),
                    step=None,
                    marks={str(year): str(year) for year in df['year'].unique()}
                )
                ],style={'width':'49%','display':'inline-block', 'float':'left'}),            
                html.Div([
                    html.Div([
                        dcc.Graph(id='graph-with-slider2'),
                        dcc.Slider(
                            id='year-slider',
                            min=df['year'].min(),
                            max=df['year'].max(),
                            value=df['year'].min(),
                            step=None,
                            marks={str(year): str(year) for year in df['year'].unique()}
                        )
                    ]),
                    html.Div([
                        dcc.Graph(id='graph-with-slider3'),
                        dcc.Slider(
                            id='year-slider',
                            min=df['year'].min(),
                            max=df['year'].max(),
                            value=df['year'].min(),
                            step=None,
                            marks={str(year): str(year) for year in df['year'].unique()}
                        )
                    ])
                ],style={'width':'49%','display':'inline-block', 'float':'right'})
        ])

div2=html.Div([     
    html.H3("Title")])

app.layout = dcc.Tabs(id="tabs", children=[
    dcc.Tab(label = 'First tab', children = div1),
    dcc.Tab(label = 'Second tab', children = div2)
])

@app.callback(
    dash.dependencies.Output('graph-with-slider', 'figure'),
    [dash.dependencies.Input('year-slider', 'value')])
def update_figure(selected_year):
    filtered_df = df[df.year == selected_year]
    traces = []
    for i in filtered_df.continent.unique():
        df_by_continent = filtered_df[filtered_df['continent'] == i]
        traces.append(go.Scatter(
            x=df_by_continent['gdpPercap'],
            y=df_by_continent['lifeExp'],
            text=df_by_continent['country'],
            mode='markers',
            opacity=0.7,
            marker={
                'size': 15,
                'line': {'width': 0.5, 'color': 'white'}
            },
            name=i
        ))

    return {
        'data': traces,
        'layout': go.Layout(
            xaxis={'type': 'log', 'title': 'GDP Per Capita'},
            yaxis={'title': 'Life Expectancy', 'range': [20, 90]},
            height=500,
            margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
            legend={'x': 0, 'y': 1},
            hovermode='closest'
        )
    }


@app.callback(
    dash.dependencies.Output('graph-with-slider2', 'figure'),
    [dash.dependencies.Input('year-slider', 'value')])
def update_figure(selected_year):
    filtered_df = df[df.year == selected_year]
    traces = []
    for i in filtered_df.continent.unique():
        df_by_continent = filtered_df[filtered_df['continent'] == i]
        traces.append(go.Scatter(
            x=df_by_continent['gdpPercap'],
            y=df_by_continent['lifeExp'],
            text=df_by_continent['country'],
            mode='markers',
            opacity=0.7,
            marker={
                'size': 15,
                'line': {'width': 0.5, 'color': 'white'}
            },
            name=i
        ))

    return {
        'data': traces,
        'layout': go.Layout(
            xaxis={'type': 'log', 'title': 'GDP Per Capita'},
            yaxis={'title': 'Life Expectancy', 'range': [20, 90]},
            height=240,
            margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
            legend={'x': 0, 'y': 1},
            hovermode='closest'

        )
    }

@app.callback(
    dash.dependencies.Output('graph-with-slider3', 'figure'),
    [dash.dependencies.Input('year-slider', 'value')])
def update_figure(selected_year):
    filtered_df = df[df.year == selected_year]
    traces = []
    for i in filtered_df.continent.unique():
        df_by_continent = filtered_df[filtered_df['continent'] == i]
        traces.append(go.Scatter(
            x=df_by_continent['gdpPercap'],
            y=df_by_continent['lifeExp'],
            text=df_by_continent['country'],
            mode='markers',
            opacity=0.7,
            marker={
                'size': 15,
                'line': {'width': 0.5, 'color': 'white'}
            },
            name=i
        ))

    return {
        'data': traces,
        'layout': go.Layout(
            xaxis={'type': 'log', 'title': 'GDP Per Capita'},
            yaxis={'title': 'Life Expectancy', 'range': [20, 90]},  
            height=240,
            margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
            legend={'x': 0, 'y': 1},
            hovermode='closest'
        )
    }

if __name__ == '__main__':
    app.run_server()
1 Like

Thanks for reporting! I think that this issue has been reported here: https://github.com/plotly/dash-core-components/issues/256. We’re working on a fix, so follow that issue for now. We also mentioned this in the docs: https://dash.plot.ly/dash-core-components/tabs and I recommend using callbacks to update the tabs now instead of embedding the content inside the children

2 Likes