Select all currently displayed options from dropdown

Hello,

Dash beginer & non programmer here : )
I’ve found lots of similar questions both here & on stackoverflow; and i’ve also looked at the different dropdown variants available on dbc and dash mantis but couldn’t find what i’ve been looking for.

When a dropdown is searchable, i would like to be able to select all the options displayed by the search value, either with a click or a key stroke.

See below minimal example & screenshots :

from dash import Dash, html, dcc, callback, Input, Output


app = Dash(__name__)
server = app.server

options = [
    'foo-1',
    'foo-2',
    'fifoo',
    'bar',
    'bar2',
    'bar3'
    ]

dropdown = dcc.Dropdown(
    id = 'dropdown',
    placeholder = 'select values',
    multi = True,
    options = options
    )

display_options = html.Div(id= 'display_options')

app.layout = [
    dropdown,
    display_options
    ]

@callback(
    Output('display_options','children'),
    Input('dropdown','value'),
    prevent_initial_call=True
)
def display_options(values):
    return values
    

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

In the screenshot below i search for dropdown options that contain “fo”.
I would like to be able to select all of these options with a single action

How would you manage that ?
Many thanks for your help; and massive thanks to the plotly dash team & community for this kickass library.

After rechecking dropdowns documentation, i cooked up something that does what I want.
I have doubt about scalability though considering that i’m accessing dropdown.options each time I input something in search_value.
Plus implementation hassle with patternmatching when there are lots of different dropdowns.

ezgif-2fd1a75c484a5b

# -*- coding: utf-8 -*-
"""
Created on Sun Mar  2 22:28:54 2025

@author: aleclair
"""
from dash import Dash, html, dcc, callback, Input, Output,State, Patch
from dash.exceptions import PreventUpdate


app = Dash(__name__)
server = app.server

options = [
    'foo-1',
    'foo-2',
    'fifoo',
    'bar',
    'bar2',
    'bar3'
    ]

dropdown = html.Div(id = 'dropdown&button',children = [
    html.Button('x',id = 'select_all_displayed_options', n_clicks = 0),
    dcc.Dropdown(
        id = 'dropdown',
        placeholder = 'select values',
        multi = True,
        options = options,
        style = {'width' : '50%'}
        ),
    dcc.Store('last_search_value')
    ])

last_search_value = html.Div(id = 'print_last_search_value')

app.layout = [
    dropdown,
    last_search_value
    ]

@callback(
    Output("last_search_value", "data",allow_duplicate=True),
    Input("dropdown", "search_value"),
    prevent_initial_call=True    
)
def update_options(search_value):
    if not search_value:
        raise PreventUpdate
    return search_value
     
@callback(
    Output("dropdown", "value"),
    Output("last_search_value", "data",allow_duplicate=True),
    Input("select_all_displayed_options", "n_clicks"),
    State("last_search_value","data"),
    State("dropdown", "options"),
    prevent_initial_call=True    
)
def update_select_all_displayed_options(n,search_value,options):
    if not search_value:
        raise PreventUpdate
    cond1=isinstance(options[0],dict)
    if cond1:
        temp = [val.get('value') for val in options if search_value in val.get('label')]
    else :
        temp = [val for val in options if search_value in val]
    return temp, str()

    
@callback(
    Output('print_last_search_value','children'),
    Input('last_search_value','data')
)
def print_last_search_value(data):
    return f'the last search_value is {data}'

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

Hi!

I don’t think that there is a built in component to do what you want.

The best solution would be to design your own React component and wrap it up to dash.
But maybe it’s not easy as a beginner

What I would have done is to mix a dropdown or mantine tags input with a list of links (html.A). A click on a link element would then add the value to the dropdown/mantine tags or remove the value if it was already selected.
It will just require pattern matching callbacks to make it work.

Let me know if you would like a code example

Hi @spriteware,
I actually took a look at dash mantine documentation in the meantime and I also thought that tag inputs could do what I imagined.
But i couldn’t figure out how to use them.

I still ended using Mantine, I just shoved my dcc.dropdown in a mantine Popoverdropdown and it kind of worked out :
ezgif-8ea5c32707d035

I had to stick to what i usually do & used a helper function.
I never had or tried to use my own objects & I don’t think i would try on my own; but if you can get me started with a piece of code, yes please by all means; it’d be a great learning opportunity for me if anything.

Many thanks for your help,

from dash import Dash, html, dcc, callback, Input, Output,State, _dash_renderer, MATCH, ALL
from dash.exceptions import PreventUpdate
import dash_mantine_components as dmc

_dash_renderer._set_react_version("18.2.0")
app = Dash(__name__)
app = Dash(external_stylesheets=dmc.styles.ALL)
server = app.server

def create_dropdown_v3(col_name :'str',options: list) -> html.Div :
    # if col_name in df.select_dtypes(include = 'datetime').columns:
    #     reverse = True
    # elif col_name not in df.select_dtypes(include = 'datetime').columns:
    #     reverse = False
    b = html.Button('', id = {'type' : 'button_all_dropdown_filter', 'index' : col_name})
    s = dcc.Store(id = {'type' : 'last_search_value_dropdown_filter', 'index' : col_name})
    d = dcc.Dropdown(
            # options=sorted(list(df[col_name].astype('str').unique()),reverse = reverse),
            id = {'type' : 'dropdown_filter', 'index' : col_name},
            placeholder = col_name,
            multi = True,
            options = options,
            style = {'height' : '4 px','margin' : 'auto'}
            )
    res = dmc.Popover(
        id = {'type' : 'popover_dropdown_filter', 'index' : col_name},
        position="bottom",
        width = 500,
        withArrow=True,
        shadow="md",
        children=[
            dmc.PopoverTarget(dmc.Button(f"{col_name}")),
            dmc.PopoverDropdown(
                children = [b,d],
                )
            ],
        )
    return html.Div(id = {'type' : 'div_dropdown','index' : col_name},children = [res,s],style = {'margin' : '1 px'})


options_list = [
    'foo-1',
    'foo-2',
    'fifoo',
    'bar',
    'bar2',
    'bar3'
    ]
options_labels = [{'value' : val, 'label': val + val[::-1]} for val in options_list]

dropdown_selection = html.Div(id = 'dropdown_selection')

app.layout = dmc.MantineProvider(
    [
    html.Div(children=[
        html.Div(children = [create_dropdown_v3('dropdown_list',options_list),
                             create_dropdown_v3('dropdown_labels',options_labels)
                             ],
                 style = {'display': 'inline-block', 'margin-left': '15px'}),
        html.Br(),
        dropdown_selection])
    ]
    )

@callback(
    Output({'type': 'last_search_value_dropdown_filter', 'index': MATCH}, "data",allow_duplicate=True),
    Output({'type': 'button_all_dropdown_filter', 'index': MATCH}, "children",allow_duplicate=True),
    Input({'type': 'dropdown_filter', 'index': MATCH}, "search_value"),
    prevent_initial_call = True
)
def update_last_search_value(search_value):
    if not search_value:
        raise PreventUpdate
    return search_value, f'add all {search_value}'

@callback(
    Output({'type': 'last_search_value_dropdown_filter', 'index': MATCH}, "data",allow_duplicate=True),
    Output({'type': 'button_all_dropdown_filter', 'index': MATCH}, "children",allow_duplicate=True),
    Input({'type': 'popover_dropdown_filter', 'index': MATCH}, "opened"),
    prevent_initial_call = True
)
def reset_search_value(opened):
    if not opened:
        raise PreventUpdate
    return '',''

@callback(
    Output({'type': 'dropdown_filter', 'index': MATCH}, 'value', allow_duplicate=True),
    Output({'type': 'last_search_value_dropdown_filter', 'index': MATCH}, 'data',allow_duplicate=True),
    Output({'type': 'button_all_dropdown_filter', 'index': MATCH}, 'children',allow_duplicate=True),
    Input({'type': 'button_all_dropdown_filter', 'index': MATCH}, 'n_clicks'),
    State({'type': 'last_search_value_dropdown_filter', 'index': MATCH},'data'),
    State({'type': 'dropdown_filter', 'index': MATCH}, 'options'),
    State({'type': 'dropdown_filter', 'index': MATCH}, 'value'),
    prevent_initial_call=True    
)
def add_all_displayed_options_to_selection(n,search_value,options,current_values):
    if not search_value:
        raise PreventUpdate
    if current_values in [None]:
        current_values = []
    cond1=isinstance(options[0],dict)
    if cond1:
        temp = [val.get('value') for val in options if str(search_value).lower() in str(val.get('label')).lower()]
    else :
        temp = [val for val in options if str(search_value).lower() in str(val).lower()]
    return current_values+temp, str(), str()

    
@callback(
    Output('dropdown_selection','children'),
    Input({'type': 'dropdown_filter', 'index': ALL}, 'value'),
)
def print_current_values(values):
    return f'selected values :  {values}'

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