✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
🐇 Announcing Dash VTK for 3d simulation graphics. Check out the March webinar.

Dropdown Callbacks Within Tabs

Hi,

I am trying to create a dashboard that has six tabs. In one of the tabs, I am incorporating four dropdown inputs connecting to a graph in one of the tabs. When I first started building the dashboard, I had no trouble with creating the tabs and requisite graphs. However when I incorporated dropdowns into the second tab, I started getting all sorts of syntax errors related to the creation of tabs. My code can be seen below:

app=dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout =html.Div(children=[
html.H1('Tennis Inventory Dashboard', style={'textAlign': 'center', 'fontSize': 48}),
html.Div([dcc.Tabs(id="tabs", value='tab-1', children=[
    dcc.Tab(label='Total', value='tab-1'),
    dcc.Tab(label='Babolat', value='tab-2'),
    dcc.Tab(label='Head', value='tab-3'),
    dcc.Tab(label='Wilson', value='tab-4'),
    dcc.Tab(label='Dunlop', value='tab-5'),
    dcc.Tab(label='Tecnofibre', value='tab-6'),
    dcc.Tab(label='Slazenger', value='tab-7')
    ]),
html.Div(id='tabs-content')]),
])
@app.callback(Output('tabs-content', 'children'),
          [Input('tabs', 'value')]) 
        
def render_content(tab):
if tab =='tab-1':
    return html.Div([
    html.H3('Average Inventory of All Brands', style={'textAlign':'center', 'fontSize': 24}),
dcc.Graph(figure=go.Figure(data=[go.Scatter(x=Totalx,y=Totaly,mode='lines+markers')],
layout=go.Layout(title='Total Inventory',xaxis={
'title':'2018'},yaxis={
'title':'Production'},
hovermode='closest',
)),
id='linear-1')
    ]),
elif tab =='tab-2':
    return html.Div([
    html.H3('Inventory', style={'textAlign':'center'}),
    dcc.Dropdown(
    id='country', 
    options=[
        {'label': i, 'value': i} for i in americas_labels],
    value=['Argentina'],#default checked items
    stye={'width':'20%','display':'inline-block'} 
),
dcc.Dropdown(
    id='Equipment_Type', #setting up the id to connect to the dash callback ( connecting checklist to figure)
    options=[
        {'label': i, 'value': i} for i in Equipment_Type],
    value=['Tennis String'],#default checked items
    style={'width':'20%','display':'inline-block'}
),
dcc.RadioItems(
    id='Volume_Sales', #setting up the id to connect to the dash callback ( connecting checklist to figure)
    options=[
        {'label': 'Volume', 'value': 'Volume'},
        {'label': 'Sales', 'value': 'Sales'}
    ],
    value=['Volume'],
    style={'width':'10%','display':'inline-block'} #default checked items
),
dcc.Dropdown(
    id='Equipment_Sub_Category', 
    options=[
        {'label': i, 'value': i} for i in Equipment_Sub_Category],
    value=['Synthetic'],
    style={'width':'40%','display':'inline-block'} #default checked items
),
    dcc.Graph(id='linear')
    ])
@app.callback(
dash.dependencies.Output('linear','figure'),
[dash.dependencies.Input('country','value'),
dash.dependencies.Input('Equipment_Type','value'),
dash.dependencies.Input('Volume_Sales','value'),
dash.dependencies.Input('Equipment_Sub_Category','value')])
def update_graph(country_name,type_name,volumeorsales,category_name):
 Filtered_Babolat=Babolat[[Babolat['country'] == country_name] & Babolat[Babolat['Equipment_Type'] ==type_name] & Babolat[Babolat['Volume_Sales'] ==volumeorsales] & Babolat[Babolat['Equipment_Sub_Category'] ==category_name]] 
 Filtered_Babolat_x=Filtered_Babolat.Quarter.unique()
 Filtered_Babolat_y=Filtered_Babolat.Value
 return {'data':[go.Scatter(x=Filtered_Babolat_x,y=Filtered_Babolat_y,mode='lines+markers')],
        'layout':go.Layout(xaxis={'title':'2018'},
                           yaxis={'title':'Production'},
                           hovermode='closest')} 
 elif tab == 'tab-3':
            return html.Div([
            html.H3('Inventory', style={'textAlign':'center'}),
            dcc.Graph(id='scatter1', figure={'data':[
            go.Scatter(
            x=Headx,
            y=Heady,
            mode='lines+markers')
            ],'layout':[go.Layout(xaxis={
            'title':'2018'},yaxis={
            'title':'Production'},
            hovermode='closest',
            ) # fill out layout
            ]} #ending the figure
            )
            ])# ending the div

The error I keep getting now is a syntax error on " elif tab==‘tab-3’, but I am wondering if it has to do with the way I set up my callbacks for my dropdowns in tab 2 since I keep getting tab errors and I did not have any before setting up the callbacks in tab 2. Any help would be greatly appreciated, thanks!

If you comment out the callback do you still get that error?

You should be able to move the callback you have in the ‘tab-2’ section outside as its own callback, you don’t need to return it with tab selection.

Also one thing to keep in mind is that you cannot use the same id twice withing the app, that will cause some issues if you do.

Hi Vantaka,

So changing the location of the dropdown callbacks definitely worked as it is now generating the tabs and the dropdowns. The only issue I have now is that the graph doesn’t generate when I select from the dropdown due to a value error " ValueError: Arrays were different lengths: 12690 vs 1". I know my csv has 12,690 rows in total so I am thinking the issue is with only this part of the code ( the function incorporating all the values of the dropdowns):

app.callback(
dash.dependencies.Output('linear','figure'),
[dash.dependencies.Input('country','value'),
dash.dependencies.Input('Equipment_Type','value'),
dash.dependencies.Input('Volume_Sales','value'),
dash.dependencies.Input('Equipment_Sub_Category','value')])
def update_graph(country_name,type_name,volumeorsales,category_name):
 Filtered_Babolat=Babolat[[Babolat['Country'] == country_name] & Babolat[Babolat['Equipment_Type'] ==type_name] & Babolat[Babolat['Volume_Sales'] ==volumeorsales] & Babolat[Babolat['Equipment_Sub_Category'] ==category_name]] #creating column values where the variables pass through to reflect new changes in dropdown
 Filtered_Babolat_x=Filtered_Babolat.Quarter.unique()
 Filtered_Babolat_y=Filtered_Babolat.Value
 return {'data':[go.Scatter(x=Filtered_Babolat_x,y=Filtered_Babolat_y,mode='lines+markers')],
        'layout':go.Layout(xaxis={'title':'2018'},
                           yaxis={'title':'Production'},
                           hovermode='closest')}

Do I need to create a for loop within the function or something instead of adding all these conditional values to the created Filtered_Babolat data frame so that it generates only one value? Or is there something else I am missing? Thanks for all the help so far!