plotly / dash

Data Apps & Dashboards for Python. No JavaScript Required.
https://plotly.com/dash
MIT License
21.42k stars 2.06k forks source link

Dash Callback function not responding; Error: Duplicate Callback Output #1544

Closed SambitD23 closed 3 months ago

SambitD23 commented 3 years ago

I am trying to create a dashboard consisting of 8 buttons, each of which corresponds to a filtered df and 4 dropdowns. The attempt was to take the filtered df according to the triggered button and use 4 columns of the df for 'options' of 4 different dcc.dropdown. But dash shows this error message:

In the callback for output(s): MBD.options Urbanity.options Outlet.options Chain.options Output 1 (Urbanity.options) is already in use. Any given output can only have one callback that sets it. To resolve this situation, try combining these into one callback function, distinguishing the trigger by using dash.callback_context if necessary.

My callback is:
@app.callback([Output('MBD', 'options'), Output('Urbanity', 'options'), Output('Outlet', 'options'),
           Output('Chain', 'options')],
           [Input('all','id'), Input('fmcg','id'), Input('bev','id'), Input('tob','id'),
           Input('food','id'), Input('drug','id'), Input('liquor','id'), 
           Input('unilever','id')])
def update_dd(all_b, fmcg_b, bev_b, tob_b, food_b, drug_b, liq_b, unil_b):
    ctx = dash.callback_context
    dff = pd.DataFrame()

if not ctx.triggered:
    button_id  = 'all.id'
else:
    button_id = ctx.triggered[0]['prop_id']
if button_id == 'all.id' :
    dff = alloutlet_df.copy()
elif button_id == 'fmcg.id':
    dff = fmcg_df.copy()
elif button_id == 'bev.id':
    dff = bev_df.copy()
elif button_id == 'tob.id':
    dff = tob_df.copy()
elif button_id == 'food.id':
    dff = food_df.copy()
elif button_id == 'drug.id':
    dff = drug_df.copy()
elif button_id == 'liquor.id':
    dff = liquor_df.copy()
elif button_id == 'unilever.id':
    dff = unilever_df.copy()
else:
    dff = df.copy()

mbd_opt = {'label':dff['Region'].unique(), 'value':dff['Region'].unique()} 
urb_opt = {'label':dff['Urbanity'].unique(), 'value': dff['Urbanity'].unique()} 
out_opt = {'label':dff['Outype_panel'].unique(), 'value':dff['Outype_panel'].unique()} 
chain_opt = {'label':dff['CHAIN'].unique(), 'value':dff['CHAIN'].unique()} 
return [mbd_opt, urb_opt, out_opt, chain_opt]
nickmelnikov82 commented 2 years ago

There is a wrong use of callbacks, here is a working example:

import dash
from dash import html
from dash import dcc
from dash.dependencies import Input, Output

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

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

app.layout = html.Div(
        [
            html.Button("fire callback1", id="all", n_clicks=1),
            html.Button("fire callback2", id="fmcg", n_clicks=2),
            html.Button("fire callback3", id="bev", n_clicks=3),
            html.Button("fire callback4", id="tob", n_clicks=4),
            html.Button("fire callback5", id="food", n_clicks=5),
            html.Button("fire callback6", id="drug", n_clicks=6),
            html.Button("fire callback7", id="liquor", n_clicks=7),
            html.Button("fire callback8", id="unilever", n_clicks=8),
            dcc.Dropdown(id="MBD"),
            dcc.Dropdown(id="Urbanity"),
            dcc.Dropdown(id="Outlet"),
            dcc.Dropdown(id="Chain"),
        ])

@app.callback([Output('MBD', 'options'), Output('Urbanity', 'options'), Output('Outlet', 'options'),
           Output('Chain', 'options')],
           [Input('all','n_clicks'), Input('fmcg','n_clicks'), Input('bev','n_clicks'), Input('tob','n_clicks'),
           Input('food','n_clicks'), Input('drug','n_clicks'), Input('liquor','n_clicks'), 
           Input('unilever','n_clicks')])
def update_dd(all_b, fmcg_b, bev_b, tob_b, food_b, drug_b, liq_b, unil_b):
    ctx = dash.callback_context

    button_id = ctx.triggered[0]['prop_id']
    value = ctx.triggered[0]['value']

    mbd_opt = {'label': button_id, 'value': value} 
    urb_opt = {'label': button_id, 'value': value} 
    out_opt = {'label': button_id, 'value': value} 
    chain_opt = {'label': button_id, 'value': value} 
    return [mbd_opt, urb_opt, out_opt, chain_opt]

if __name__ == '__main__':
    app.run_server(debug=True)
gvwilson commented 3 months ago

Hi - we are tidying up stale issues and PRs in Plotly's public repositories so that we can focus on things that are most important to our community. If this issue is still a concern, please add a comment letting us know what recent version of our software you've checked it with so that I can reopen it and add it to our backlog. (Please note that we will give priority to reports that include a short reproducible example.) If you'd like to submit a PR, we'd be happy to prioritize a review, and if it's a request for tech support, please post in our community forum. Thank you - @gvwilson