Pre-selected Multi-Select Box with Search Capability in Streamlit

Hi Streamlit Community,

I’m working on a Data Visualization app using Streamlit and have implemented selectbox and multiselect components for user interaction. However, I’m facing an issue with the multiselect component.

Issue:
I want the multiselect box to have all options pre-selected by default without explicitly showing all the options in the selection area. Currently, one of my filters has around 70 options, and it shows all of them upon loading, which is overwhelming and cluttered.

Desired Behavior:
I’m aiming for functionality similar to what I achieved in Google Looker Studio, where:

  1. All options are pre-selected by default.
  2. The dropdown remains collapsed initially.
  3. When the user clicks on the dropdown, it expands to show the options.
  4. The dropdown should include a search feature for easy filtering within the options.

Has anyone implemented something similar in Streamlit? Any suggestions or best practices to achieve this behaviour would be greatly appreciated!

Filter 1
filter 2
t a screenshot).
Filter 3

Github:GitHub - MathankumarSelvaraj/airexportdashboard
Dashboard: https://mathandashboard.streamlit.app/

1 Like

That looks more like check buttons than multiselect.

Yes Check button inside the multi select

I guess you could put the search box and the check boxes in an expander.

with st.expander(label="Select"):
    st.text_input(label="Filter")
    with st.container(height=200):
        for n in range(100):
            st.checkbox(label=f"option #{n}")

You need to add the filtering logic and find a way to store the selections independently of the filtering.

You can wrap two popovers in a container. And wrap search text box and airlines checkboxes in airline popover. Do the same for year popover.

Sample airline popover.

Sample complete code.

import streamlit as st
import pandas as pd
from st_keyup import st_keyup


if 'yr_result' not in st.session_state:
    st.session_state.yr_result = None
if 'airline_result' not in st.session_state:
    st.session_state.airline_result = None


DATAFRAME_HEIGTH = 150


data = {
    'Year': [
        '2020', '2020', '2020', '2020', '2020', '2020', '2020', '2020', '2020', '2020',
        '2021', '2021', '2021', '2021', '2021', '2021', '2021', '2021', '2021', '2021',
        '2022', '2022', '2022', '2022', '2022', '2022', '2022', '2022', '2022', '2022',
        '2023', '2023', '2023', '2023', '2023', '2023', '2023', '2023', '2023', '2023',
        '2024', '2024', '2024', '2024', '2024', '2024', '2024', '2024', '2024', '2024'
    ],
    'Airlines': [
        'Philippine Airlines', 'Japan Airlines', 'China Airlines', 'American Airlines',
        'Qantas', 'Emirates', 'Delta Airlines', 'United Airlines', 'British Airways',
        'Air France', 'Philippine Airlines', 'Japan Airlines', 'China Airlines',
        'American Airlines', 'Qantas', 'Emirates', 'Delta Airlines', 'United Airlines',
        'British Airways', 'Air France', 'Philippine Airlines', 'Japan Airlines',
        'China Airlines', 'American Airlines', 'Qantas', 'Emirates', 'Delta Airlines',
        'United Airlines', 'British Airways', 'Air France', 'Philippine Airlines',
        'Japan Airlines', 'China Airlines', 'American Airlines', 'Qantas', 'Emirates',
        'Delta Airlines', 'United Airlines', 'British Airways', 'Air France',
        'Philippine Airlines', 'Japan Airlines', 'China Airlines', 'American Airlines',
        'Qantas', 'Emirates', 'Delta Airlines', 'United Airlines', 'British Airways',
        'Air France'
    ]
}


def change_year_cb(df):
    st.session_state.yr_result = filter_by_year(
        df, st.session_state.txt_searchyeark)


def filter_by_year(df, year):
    filtered_df = df[df['Year'] == year]
    unique_year = filtered_df['Year'].unique()
    return unique_year


def change_airline_cb(df):
    st.session_state.airline_result = filter_by_airline(
        df, st.session_state.txt_searchairlinek)


def filter_by_airline(df, airline):
    filtered_df = df[df['Airlines'].str.contains(airline, case=False)]
    unique_airlines = filtered_df['Airlines'].unique()
    return unique_airlines


df = pd.DataFrame(data)
    
con_cols = st.columns([2, 1])
with con_cols[0]:
    with st.container(border=True):
        st.markdown('**Please Select Filters**')

        with st.popover(label='Year', use_container_width=True):
            cols = st.columns([2, 1], gap='small')
            with cols[0]:
                st_keyup("Search Year", key='txt_searchyeark',
                         on_change=change_year_cb, args=(df,),
                         placeholder='type to search')
                st.dataframe(st.session_state.yr_result, hide_index=True,
                             use_container_width=True, height=DATAFRAME_HEIGTH)

            # Shows year checkboxes
            for y in df['Year'].unique():
                st.checkbox(y, value=True, key=y)

        with st.popover(label='Airlines', use_container_width=True):
            cols = st.columns([2, 1], gap='small')
            with cols[0]:
                st_keyup('Search Airlines', key='txt_searchairlinek',
                         on_change=change_airline_cb, args=(df,),
                         placeholder='type to search')
                st.dataframe(st.session_state.airline_result, hide_index=True,
                             use_container_width=True, height=DATAFRAME_HEIGTH)

            # Shows airline checkboxes
            for a in df['Airlines'].unique():
                st.checkbox(a, value=True, key=a)

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.