Background image
11.11.2024, Kai Gertz

select-improved: an improved select component

The work at Tojio has resulted in an improved select component, which we publish as an open source widget.

We have created a customized select widget specifically for multiple selections at Tojio. The problem with the conventional select element:

  • it is very difficult to customize visually
  • it can't be filtered (which is particularly annoying for long lists)
  • if multiple selection is possible, you can no longer see the selected options after collapsing the list

For the calendar of events for Climate Adaptation Week (hosted by Zentrum KlimaAnpassung - German Climate Adaptation Center), we have added various filter options: above the events, you can filter by the individual days of the week. Below this, behind a "Set filter" button, there is an initially collapsed area with further options for filtering events according to certain criteria (e.g. federal state).

For filters of this type that use long select lists, we have created a strongly improved web component that replaces the native select element.

Screenshot of an improved select comonent with the possibility to filter the list and a separate display of selected options

Our improved select widget: select-improved

Extending the native select element

Our select-improved is a web component that extends the native select element.

class SelectImproved extends HTMLSelectElement {

[...]

}
customElements.define('select-improved', SelectImproved, { extends: 'select' });

Functionality of the component

A web component that extends existing elements is not embedded with its own tag name as usual, but the original element is extended by the attribute is, in which the extension class is specified: <select is="select-improved">This means that we have to change the Twig template in the places that are to use the new element and insert the attribute there (see below).

{% set replacement_info =  'is=select-improved' %}
{{ attach_library('zka/custom-elements-polyfill') }}
{{ attach_library('zka/select-improved') }}

{% apply spaceless %}
  <select{{ attributes }} {{ replacement_info }}>

    {# [...] options as usual  #}
 
  </select>
{% endapply %}

The extended component takes the options as they are passed to the select element and builds a new, visual representation with filter, list and an area for displaying selected options (for multiple selections) within the shadow root of the component.

Polyfill for browsers that do not support extensions of native elements

Unfortunately, not all browsers (especially not Safari on MacOS / iOS, nor WebView on iOS) support extending existing HTML elements (too bad Apple, Safari used to be a really nice, progressive piece of software). A longer issue in the WebKit project presents the discussion on this.

In order for our custom select element to also work in Safari, a polyfill must be used to enable this functionality in Safari. The polyfill comes from the Ungap project and we define an own library for this purpose, which is loaded first. To ensure that this library is available before a custom element can even be instantiated, we force it to be loaded in the document header:

custom-elements-polyfill:
  version: 1.0
  # it is crucial that this available before any other custom element
  # stuff so move it into the header 
  header: true
  js:
    # polyfill needed for safari
    components/select-improved/custom-elements.1.3.0.min.js: { minified: true }

select-improved:
  version: 1.0
  js:
    # definition of the web component
    components/select-improved/select-improved.js: {}
  css:
    theme:
      # this css holds the custom properties to adjust styling
      components/select-improved/select-improved.css: {}

Our improved select component can be downloaded for use in the Gitlab Repo.