Particularly for my specific situation, using the dcc.Dropdown works perfectly. The only problem is that in many situations, the user might select multiple options, which will look really ugly visually.
Is there a way to make the dropdown like this image below:
I have already thought about creating a menu that opens with options that can be selected as a checklist, but that would be more complex to code because I want to allow the user to search for the option they want just like in the standard dcc.Dropdown
This dropdown is almost perfect, but due to the complexity of the search, I still need an input that searches and filters the options similar to Google Sheets filter or native dcc.Dropdown.
To be honest, that topic helped me more than I imagined because by showing examples and what I actually wanted, I ended up thinking of the solution. I just needed to make a small adaptation.
Solution:
import dash_bootstrap_components as dbc
from dash import Dash, html, dcc, Input, Output, callback
import pathlib
import pandas as pd
import numpy as np
options = [f"option_{idx}" for idx in range(6)]
options.extend([f"{idx}_option" for idx in range(6)])
dropdown_items_list = [dcc.Input(id="input_search", type="text", value="")]
for idx, items in enumerate(options):
dropdown_item = dcc.Checklist(
id=f"check-{idx}",
options=[items],
)
dropdown_items_list.append(dropdown_item)
app = Dash(
external_stylesheets=[
[pathlib.Path("assets", "style")],
dbc.themes.BOOTSTRAP,
]
)
app.layout = html.Div(
[
dbc.DropdownMenu(
id="dropdown-menu",
children=dropdown_items_list,
toggle_style={"width": "17svh"},
),
],
className="selector_containerFinal",
style={"justify-content": "center"},
)
def generate_input_ids(prefix, values):
return [Input(f"{prefix}-{value}", "value") for value in values]
def generate_output_ids(prefix, values):
return [Output(f"{prefix}-{value}", "className") for value in values]
@callback(
Output("dropdown-menu", "label"),
generate_input_ids("check", range(len(options))),
)
def show_options(*selected_values):
selected = [
val
for sublist in selected_values
if sublist is not None
for val in sublist
]
if len(selected) == 1:
return selected[0]
if len(selected) > 1 and len(selected) < len(options):
return "Multiple options"
if len(selected) == len(options):
return "All"
return "All"
@callback(
generate_output_ids("check", range(len(options))),
Input("input_search", "value"),
)
def filter_options(searched_text):
return tuple(
np.where(
pd.Series(options).str.contains(searched_text,case='False'),
"", "hidden"
)
)
if __name__ == "__main__":
app.run(debug=True)