Multi-select “All” option in Streamlit

Carlos D Serrano
Streamlit
Published in
3 min readMar 31, 2023

When using the Streamlit multiselect widget, we often need a way to select all items and with a widget with many options, this can be a lot of work. This simple solution uses a callback function and a few session state variables to adapt the behavior of this widget to allow an “All” option at the beginning of our options list.

For this example, we need a list of 11 items. Note that our list begins with -1. I’ll use this negative number on my formatting function to inject the “All Option.” I’ll also declare a session state variable called“max_selections” and initially set it to the length of our list.

available_options = [i for i in range(-1, 10)]
if "max_selections" not in st.session_state:
st.session_state["max_selections"] = len(available_options)

Callback Function

This callback function will be bound to the on_change parameter of our multiselect widget. Callback functions execute before the rest of the code executes on a triggered event. Read more about these here. Because callback functions use session state, I will evaluate whether “selected_options,” which belongs to the “key” parameter of the multiselect widget, exists in the app session state. This evaluation will prevent an uninitialized variable error. Then, I will evaluate if -1, a value bound to the “All” option, exists in the list of items selected in the multiselect widget. If true, I will set my “selected_options” to only the first item on the list and set the “max_selections” variable to 1 to prevent more options from being selected. If false, it will set the “max_selections” variable back to the length of the source list.

def options_select():
if "selected_options" in st.session_state:
if -1 in st.session_state["selected_options"]:
st.session_state["selected_options"] = [available_options[0]]
st.session_state["max_selections"] = 1
else:
st.session_state["max_selections"] = len(available_options)

Widget

Now, the multiselect widget will use a few parameters:

  1. Label
  2. options: Set to the list we created in the first step.
  3. key: This will create a session state variable for this widget.
  4. max_selections: This value is programmatically adjusted in the first step and the callback function.
  5. on_change: This will invoke the callback function every time there is a new change on this widget.
  6. format_func: For this example, we’re using a lambda function to format the items on our widget without changing the output. In this parameter, it’s when -1 becomes “All”.
st.multiselect(
label="Select an Option",
options=available_options,
key="selected_options",
max_selections=st.session_state["max_selections"],
on_change=options_select,
format_func=lambda x: "All" if x == -1 else f"Option {x}",
)

Display the output

I use a simple “write” widget with an IF statement to determine whether to display all but -1 or the selected options.

st.write(
available_options[1:]
if st.session_state["max_selections"] == 1
else st.session_state["selected_options"]
)

Results

Full code

import streamlit as st


def options_select():
if "selected_options" in st.session_state:
if -1 in st.session_state["selected_options"]:
st.session_state["selected_options"] = [available_options[0]]
st.session_state["max_selections"] = 1
else:
st.session_state["max_selections"] = len(available_options)


available_options = [i for i in range(-1, 10)]
if "max_selections" not in st.session_state:
st.session_state["max_selections"] = len(available_options)

st.multiselect(
label="Select an Option",
options=available_options,
key="selected_options",
max_selections=st.session_state["max_selections"],
on_change=options_select,
format_func=lambda x: "All" if x == -1 else f"Option {x}",
)

st.write(
available_options[1:]
if st.session_state["max_selections"] == 1
else st.session_state["selected_options"]
)

--

--

Carlos D Serrano
Streamlit

Sr. Solution Innovation Architect @ Snowflake • Streamlit • DataOps • Hispanic Data Community Leader • 🇵🇷 ▶️ 🇺🇸