Sheryna
Sheryna

Reputation: 77

Adding 'Select All' option in Plotly/Dash dropdown

I am pretty new to Plotly/Dash and currently struggling to add a 'Select All' option for my dropdown especially on the callback. Please help, been stuck on this for a some time.

app = dash.Dash(__name__)

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

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

all = df.Pillar.unique()

options=[{'label':x , 'value':x} for x in all]
options.append({'label': 'Select All', 'value': "all"})

app.layout=html.Div([
    html.H1("PRO Project Management dashboard"),
    
        html.Div([
        html.P('Pillar'),
        dcc.Dropdown(id='pillar-choice', options=[{'label':x , 'value':x} for x in all] + [{'label':'Select All' , 'value':'all'}] , value= 'for', multi=True),
    ]),
        
       
    html.Div([
            dcc.Graph(id='graph1', style={'display':'inline-block', 'width' :'33%'})
        
    ]),
    
])

@app.callback(
    Output(component_id='graph1', component_property='figure'),
    Input(component_id='pillar-choice', component_property='value') 
)

def update_graph1(value_pillar):
    if value_pillar == 'all':
        dff = df
    else:
        dff = df[df.Pillar.isin([value_pillar])]
        fig = px.pie(data_frame=dff, names='Pillar', values='Project No', title='Number of Projects by Pillars')
        return fig
    
    
if __name__=='__main__':
    app.run_server()

Upvotes: 4

Views: 8995

Answers (1)

coralvanda
coralvanda

Reputation: 6596

Your dropdowns are using all of the values from specific columns, such as:

dcc.Dropdown(id='pillar-choice', options=[{'label':x, 'value':x}] for x in all, value=all, multi=True)

To have a "select all" option, you'll need another value which your code can recognize as unique from the values that exist in the column. Something like this should work:

dcc.Dropdown(
    id='pillar-choice', 
    options=[{'label':x, 'value':x} for x in all] + [{'label': 'Select all', 'value': 'all_values'], 
    value='all_values',  
    multi=True,
)

Then, in your callback logic, you can include something like this:

@app.callback(
    Output('whichever-graph-this-goes-to', 'figure'),
    [
        Input('pillar-choice', 'value')
        # whatever other inputs
    ]
)
def my_callback(pillar_dropdown, whatever_other_args):
    if pillar_dropdown == 'all_values':
        dff = df
    else:
        dff = df[df['Pillar'].eq(pillar_dropdown)]
    # rest of callback logic

Edit: I have it working locally. Here's what the callback looks like for me now:

@app.callback(
    dash.dependencies.Output(component_id='graph1', component_property='figure'),
    [
        dash.dependencies.Input(component_id='pillar-choice', component_property='value')
    ]
)
def update_graph1(value_pillar):
    if value_pillar == ['all']:
        dff = df
    else:
        dff = df[df.Pillar.isin(value_pillar)]

    fig = px.pie(
        data_frame=dff,
        names='Pillar',
        values='Project No',
        title='Number of Projects by Pillars'
    )
    return fig

Here are the changes I made:

  1. The Input is wrapped in a list.
  2. The first condition is now wrapped in a list. This is important because the dropdown is set as multi=True, so it should always be returning a list of values. I changed the default value for the dropdown to be a list as well.
  3. The value passed to .isin() is no longer wrapped in brackets because it's already a list.
  4. The creation of the fig object is done outside the conditional statements, so that it happens regardless of which condition path executes.

Upvotes: 4

Related Questions