Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save den-run-ai/7bd22eff1e436bd68603c0c000c07879 to your computer and use it in GitHub Desktop.
Save den-run-ai/7bd22eff1e436bd68603c0c000c07879 to your computer and use it in GitHub Desktop.
Multiple checkbox selection with searching with ipywidgets

Multiple selection with checkboxes and search field

Often, you want the user to choose n options (where n is small-ish) from a very large (hundreds or thousands) number of possibilities. Good UX around this dictates that the user should be able to search for the options they want.

This gist puts together a minimal example of binding a search field with multiple checkboxes using ipywidgets.

Usage

widget = multi_checkbox_widget(['hello', 'world'])
widget # Display the widget

To get the selected options:

selected_options = [widget.description for widget in w.children[1].children if widget.value]

Possible improvements

  • This is in need of some layout/CSS TLC.

  • At the moment, we just use difflib from the standard library for searching through the options. It mostly works, but I don't think it's what difflib is supposed to be used as. Using a different search algorithm might lead to better results.

import difflib
import random
import requests
import ipywidgets as widgets
def multi_checkbox_widget(descriptions):
""" Widget with a search field and lots of checkboxes """
search_widget = widgets.Text()
options_dict = {description: widgets.Checkbox(description=description, value=False) for description in descriptions}
options = [options_dict[description] for description in descriptions]
options_widget = widgets.VBox(options, layout={'overflow': 'scroll'})
multi_select = widgets.VBox([search_widget, options_widget])
# Wire the search field to the checkboxes
def on_text_change(change):
search_input = change['new']
if search_input == '':
# Reset search field
new_options = [options_dict[description] for description in descriptions]
else:
# Filter by search field using difflib.
close_matches = difflib.get_close_matches(search_input, descriptions, cutoff=0.0)
new_options = [options_dict[description] for description in close_matches]
options_widget.children = new_options
search_widget.observe(on_text_change, names='value')
return multi_select
# Example of using the widget
# Get lots of words for our options
words_url = 'https://svnweb.freebsd.org/csrg/share/dict/words?view=co&content-type=text/plain'
response = requests.get(words_url)
response.raise_for_status()
words = response.text
words = set([word.lower() for word in words.splitlines()])
descriptions = random.sample(words, 100)
multi_checkbox_widget(descriptions)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment