'Select All' on a Streamlit Multiselect

Hi all, I’ve been trying to get a “Select All” checkbox to work on a multiselect widget by doing the following:

if st.checkbox('Select all'):
    selected_options = st.multiselect("Select one or more options:",
                                                            ['A', 'B', 'C'],
                                                            ['A', 'B', 'C'])
else:
    selected_options =  st.multiselect("Select one or more options:",
                                                            ['A', 'B', 'C'])

But the way the checkbox is shown before the multiselect widget is a bit counterintuitive, is there a way to have the checkbox after the mutliselect?

1 Like

Hey @Venide,
First, Welcome to the Streamlit Community!!! :partying_face: :partying_face: :two_hearts: :tada: :tada: :tada:

EXCELLENT QUESTION!! I’m so glad you asked! Let us dig into all the possibilities!

Option 1: all through code
This bit of code will put the checkbox after your multiselect, but if it’s checked, the options won’t show up in the multiselect as it currently does.

selected_options = st.multiselect("Select one or more options:",
    ['A', 'B', 'C'])

all_options = st.checkbox("Select all options")

if all_options:
    selected_options = ['A', 'B', 'C']

selected_options # this uses MAGIC to print the options to the screen!

Option 2: unique option in the widget
This lets the user have a drop-down option in the multiselect that takes priority and is displayed in the widget itself

selected_option_2 = st.multiselect("Select one or more options:",['A', 'B', 'C', 'All'])

if "All" in selected_option_2:
    selected_option_2 = ['A', 'B', 'C']

selected_option_2

Option 3: Containers (my fav)
This is my personal favourite! If you use the st.beta_container you can have the best of both worlds! a multiselect that populates with the options that the user selects and a checkbox the appears after it. This is because, with the power of containers, you can place objects and widgets out of order from how they are coded (yes you read that right! :star_struck:)

container = st.beta_container()
all = st.checkbox("Select all")
 
if all:
    selected_options = container.multiselect("Select one or more options:",
         ['A', 'B', 'C'],['A', 'B', 'C'])
else:
    selected_options =  container.multiselect("Select one or more options:",
        ['A', 'B', 'C'])

Here is a gif of an app where I put all these options side-by-side you you can see the differences I mean!

multiselect_all · Streamlit

Happy Streamlit-ing!
Marisa

25 Likes

Hey @Marisa_Smith,

Wanted to provide some feedback —> This answer saved me a TON of time, and got me into the st.containers (which is awesome)!

As a streamlit noob, I look forward to continuing to explore all the options and flexibility!

Thanks!

3 Likes

Hey @Yoda,

:smiling_face_with_three_hearts: It means a lot to hear that people find what we do here useful even 4 months later! :two_hearts:

Thanks for letting me know!

Happy Streamlit-ing!
Marisa

2 Likes

Hi @Marisa_Smith

I used your containers approache for a ‘select all’ on Multiselect. I know have some trubles to filter a df with it.

countries_list = df['Origin_Country'].unique()

countries = st.beta_container()
all = st.checkbox("Select all", value=True)
 
if all:
    selected_options = countries.multiselect("Select one or more Country of origin:",
        countries_list, countries_list)
else:
    selected_options =  countries.multiselect("Select one or more Country of origin:",
        countries_list)


selected_countries = df['Origin_Country'].isin(countries)

st.dataframe(selected_countries)

gives me the error TypeError: only list-like objects are allowed to be passed to isin(), you passed a [DeltaGenerator]

When I use

selected_countries = df[df['Origin_Country'] == countries] 

st.dataframe(selected_countries)

to filter I get an empty table back.

Can you or someone tell me how to filter with the containers approach?

Hey @fvr1210,

So there is a typo in your code here:

countries is the name of your container, not the list you made from your select box! This should be changed to selected_options.

If it’s unclear to you why this is the case, let me know and I can explain a bit more about containers.

Happy Streamlit-ing!
Marisa

1 Like

thanks a lot @Marisa_Smith !!!

I had to adjust the code little bit to

selected_countries = df.loc[df["Origin_Country"].isin(selected_options)]

but that is because I wanted to get the tables with the values and not with zeros and ones.

It would be great if you can post a good blog or an other source about containers (otherwise I will just us google). So that I don’t just copy and paste :wink:

1 Like

I need to select all of more than 1000 indexes in a data frame, is there any way to do it? Basically, have an option of all.

Currently, my code is

ids = st.multiselect( "Choose ids", list(df.index), ["mal", "gap"])

This can do multiple select but cannot select all of them at once.

Thanks.

Hi @Marisa_Smith ,

Thank you for the brilliant solution. This really helps.

A follow up on this - after all the options are populated in the multi select on activation of the checkbox, how do I uncheck the checkbox if say I removed one of the options from the multi select box?

For example, in the scenario you explained, when you click the ‘select all’ button, the three options : A,B & C are displayed. I want that when I click on the cross next to ‘C’ (basically not selecting it), the ‘Select All’ checkbox is unchecked. Thanks in advance :slight_smile:

Hey @Subham,

The best way to manage this now is to use the st.sessions_state feature! :partying_face:

Here is a link to a post that is super similar (its to do with radio button options and being controlled by a “next” button). The solution for this multi-select would be very similar to this!

Marisa

1 Like

A post was split to a new topic: Select all checkbox that is linked to selectbox of options

2 posts were split to a new topic: Use button to clear multiselect using session_state

Hey Marisa,
Thank for this solution saved me a lot of time, In my dashboard when I select the select all option for multi select can I make all the options selected in the box disappear or invisible?

I have a huge number of options that can be selected. this makes the user scroll through the dashboard multiple times and I feel this is bad design on my part

Any suggestions are also welcome, I was think a search tool where i can enter few char of the option and the multi select would finish it

and also how do I make the select all check box appear on the top of the multi select box

Thank you,
(Noob here just started out streamlit)

Just wanted to improve this solution, i.e. add a more elegant way that selects all options as default if you don’t choose any via multiselect:

# just check if returned array is empty
selected_options = st.multiselect('Select options:', ['A', 'B', 'C'])

# check if empty
if not selected_options:
    selected_options = ['A', 'B', 'C']

# print currently selected options
selected_options

1 Like

Excellent! Empty Multiselect mean ‘All items’ selected. This give most compact view on mobile browsers. Thanks!

I am trying to have a multiselect widget with select all option inside a form
my current solution works well outside of form

def multiselect_with_select_all(name, options, key):
    c1, c2 = st.columns([10, 3])

    c2.markdown("")
    c2.markdown("")
    container = c1.empty()

    checkbox = c2.checkbox(
        "Select All",
        help="Select All",
        key=key,
    )
    if checkbox:
        results = container.multiselect(
            name + " (All Selected)",
            options,
            options,
            disabled=True,
            help="Unselect 'Select All' Checkbox to change values",
            key=key + "_all",
        )
    else:
        results = container.multiselect(
            name,
            options,
            [],
            key=key + "_none",
        )

    return results

but inside of form I have to press submit to see the changes of the widget
Is there a way around it?

1 Like

Inside of a form, the output of any widget will not be updated until the form is submitted. If you want something to update immediately, then the thing causing the change needs to be outside of a form. (You can still have the dependent thing receiving the change be inside a form, but then it will also propagate that change through so be aware of that.)

Hi, just wanted to refer to a fourth option using st.session_state and a callback for the “Select all” button posted here: https://discuss.streamlit.io/t/select-all-button-for-multiselect/55936/4