Skip to content

Select and Select2 Fields

.c-select + .js-select2 (optional)

Select fields are used to select a single value from a list of options. This documentation covers the styling of the native select element as well as the styling and functionality of the Select2 dropdown.

Select vs. Select2

Native Select

Use the class c-select on a select element to get the default styling:
.c-float-container.-has-select > .c-select

Show Code
html
<div class="c-float-container -has-select">
  <label class="c-label" for="style-select">Select Box without Select2</label>
  <select class="c-select" id="style-select" name="opts">
    <option value='0'></option>
    <option value='1'>First item</option>
    <option value='2'>Second item</option>
    <option value='3'>Third item</option>
    <option value='4'>Lorem Ipsum</option>
    <option value='5'>lorem ipsum dolor sit amet consectetur adipisici elit</option>
    <option value='6'>lorem ipsum dolor sit amet consectetur adipisici elit</option>
    <option value='7'>adipisici elit</option>
    <option value='8'>Last item</option>
  </select>
</div>

With Select2

Use the class js-select2 on a select element if you want to initialize Select2 (Version4.1.0-rc.0).

.c-float-container.-has-select > .c-select.js-select2

Show Code
html
<div class="c-float-container -has-select">
  <label class="c-label" for="default-select">Select Box with Floating Label</label>
  <select class="js-select2" id="default-select" name="default-select">
    <option value='1'>First item</option>
    <option value='2'>Second item</option>
    <option value='3'>Third item</option>
    <option value='4'>Lorem Ipsum</option>
    <option value='5'>lorem ipsum dolor sit amet consectetur adipisici elit</option>
    <option value='6'>lorem ipsum dolor sit amet consectetur adipisici elit</option>
    <option value='7'>Just an item</option>
    <option value='8'>Last item</option>
  </select>
</div>

Light Version

.c-float-container.-has-select.-light > .c-select.-light

Show Code
html
<div class="h-highlight-block">
  <div class="c-float-container">
    <label class="c-label" for="light">Light Select Dropdown</label>
    <select class="js-select2" id="light" name="light-select" data-additional-classes="-light">
      <option value="0"></option>
      <option value='1'>First item</option>
      <option value='2'>Second item</option>
      <option value='3'>Third item</option>
    </select>
  </div>
</div>

Disabled Select

.c-select[disabled]

Show Code
html
<div class="c-float-container -has-select -is-disabled">
  <label class="c-label" for="disabled-box">Disabled Select Box</label>
  <select class="js-select2" disabled id="disabled-box" name="opts">
    <option value='1'>First item</option>
    <option value='2'>Second item</option>
    <option value='3'>Third item</option>
    <option value='4'>Lorem Ipsum</option>
    <option value='5'>lorem ipsum dolor sit amet consectetur adipisici elit</option>
    <option value='6'>lorem ipsum dolor sit amet consectetur adipisici elit</option>
    <option value='7'>Just an item</option>
    <option value='8'>Last item</option>
  </select>
</div>
<select class="m-t-xl js-select2" disabled name="disabled-link-select" data-additional-classes="-is-link">
  <option value="1" class="js-option-lager">selected item</option>
  <option value="0" class="js-option-no-lager">item</option>
</select>
<select class="m-t-xl js-select2" disabled name="disabled-link-select-small" data-additional-classes="-is-link -small">
  <option value="1" class="js-option-lager">selected item</option>
  <option value="0" class="js-option-no-lager">item</option>
</select>

Select2 with Search Field

The search field in the dropdown is hidden per default, add the attribute data-search to enable it: .js-select2[data-search]

Show Code
html
<div class="c-float-container -has-select m-b-m">
  <label class="c-label" for="select-search">Select Box with Search Field</label>
  <select class="js-select2" data-search id="select-search">
    <option value='1'>First item</option>
    <option value='2'>Second item</option>
    <option value='3'>Third item</option>
    <option value='4'>Lorem Ipsum</option>
  </select>
</div>

Select2 with Multiple Choices

(not in use yet)

<select class="js-select2" multiple ..

Show Code
html
<div class="c-float-container -has-select -is-active m-b-m">
  <label class="c-label" for="multiple-select">Multiple Select</label>
  <select class="js-select2" multiple id="multiple-select" name="multiple" data-additional-classes="">
    <option selected value='1'>First item with longer name</option>
    <option value='2'>Second item</option>
    <option value='3'>Third item</option>
    <option value='4'>Lorem Ipsum Dolor</option>
    <option value='5'> Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</option>
    <option selected value='6'> Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</option>
  </select>
</div>

Select2 Option Groups

optgroup > option ..

Show Code
html
<div class="c-float-container -has-select m-b-m">
  <label class="c-label" for="option-groups">With Option Groups</label>
  <select class="js-select2" data-search id="option-groups">
    <optgroup label="Group Name">
      <option>Nested option 1</option>
      <option>Nested option 2</option>
    </optgroup>
    <optgroup label="Group Name 2">
      <option>Nested option 1</option>
      <option>Nested option 2</option>
    </optgroup>
  </select>
</div>

Disabled Options

Add the attribute disabled to disable options in the dropdown:
<option value='...' disabled>

Show Code
html
<div class="c-float-container -has-select">
  <label class="c-label" for="diss">Select Box with Disabled Options</label>
  <select class="js-select2" id="diss" name="disabled-options1">
    <option value='1'>First item</option>
    <option value='2' disabled>Second item</option>
    <option value='3'>Third item</option>
    <option value='4' disabled>Last item</option>
  </select>
</div>

Hide Disabled Options

Add the attribute data-hide-disabled to hide disabled options in the dropdown:
.js-select2[data-hide-disabled]

Show Code
html
<div class="c-float-container -has-select">
  <label class="c-label" for="hide-disabled-opts">Select Box with Hidden Disabled Options</label>
  <select class="js-select2"  data-hide-disabled id="hide-disabled-opts" >
    <option value='1'>First item</option>
    <option value='2' disabled>Second item</option>
    <option value='3'>Third item</option>
    <option value='4' disabled>Last item</option>
  </select>
</div>

Custom Option Tags

If you want to allow custom options tags, add the attribute data-custom-options

Add the class .-is-link to the select element to get a link-style select field:
.js-select2.c-select.-is-link[.-small]

Show Code
html
<div class="h-flex h-space-around">
  <div class="h-width-40">
    <select class="js-select2 demo-link-example" name="link-select" data-additional-classes="-is-link -has-icons">
      <option value="1" class="js-option-lager">✓</option>
      <option value="0" class="js-option-no-lager">✕</option>
    </select>
  </div>
  <div class="h-width-40">
    <select class="js-select2 demo-link-example" name="link-select-small" id="link-select-small" data-additional-classes="-is-link -small">
      <option value="1" class="js-option-lager">✓</option>
      <option value="0" class="js-option-no-lager">✕</option>
    </select>
  </div>
</div>

Select2 with Icon and Tooltip

.c-float-container.-has-select.-icon-right > .c-float-container__icon

See Tooltips for more information.

Show Code
html
<div class="c-float-container -has-select -icon-right">
  <label class="c-label" for="select-info">Floating Label</label>
  <select class="js-select2" id="select-info" name="select-info-name" data-additional-classes="-icon">
    <option value='1'>First item</option>
    <option value='2'>Second item</option>
    <option value='3'>Third item</option>
    <option value='4'>Last item</option>
  </select>
  <div class="c-float-container__icon -right js-tooltip" data-title="Prüfzertifikat löschen"
       data-placement="left">
    <span class="fa fa-info-circle" aria-hidden="true"></span>
  </div>
</div>

AJAX Example (with Search and Clear-Button)

TIP

  • allowClear needs a placeholder and placeholder need a corresponding option value (which cannot be an empty string, but can be a single space)
  • Select2 AJAX support: See select2.org/data-sources/ajax
Show Code for AJAX Example
javascript
import {Select} from "./Select";
Select.init();

const $select = $(".js-example");
const mergedSelectOptions = $.extend(true, {}, Select.getOptionsWithTags("Unbekannter Bestandteil"), {
    ajax: {
        url: "https://jsonplaceholder.typicode.com/posts/", // aktuell Dummy-API, gerne auch andere Endpunkte ausprobieren!
        dataType: "json",
        allowClear: true, // always use in combination with data-placeholder attribute on element
        processResults: function (data) {
            /**
             * Wir setzen "text" (also den Text in der Zeile) hier auf den Namen des Elements.
             * Siehe https://select2.org/data-sources/formats
             * Da die Elemente von der Dummy-API ohnehin schon ein Attribut "id" haben, müssen wir das nicht extra setzen.
             */
            data.forEach(resultObj => {
                    resultObj.info = resultObj.body;
                    resultObj.text = resultObj.title;
                    Select.addOptionTagsIfNotExists($select, resultObj);
                }
            );
            return {
                results: data
            };
        }
    }
});

$select.each(function () {
    Select.apply($(this), mergedSelectOptions);
});

Fake Select2

A simple div that is not initialized by Select2 but has the same look. It can be used to display read-only values.

.c-float-container.-has-select > .c-fake-select

Sonder-PZN
09999005
Show Code
html
<div class="h-highlight-block">
  <div class="c-float-container -is-active -has-select h-hover-pointer -light m-y-reset">
    <span class="c-label">Sonder-PZN</span>
    <div class="print-hide c-float-container__icon h-help-pointer c-tooltip__trigger -left -small">
      <span class="fa fa-info-circle h-link-color" aria-hidden="true"></span>
      <div data-cy="tooltip" class="c-tooltip h-always-on-top m-t-xxs -large m-l-s m-t-s">
        Für die korrekte Erstellung von Z-Daten und Hash-Code ist die tatsächliche PZN Ihres Bestandteils anzugeben.
        Hilfstaxen-PZN bzw. Sonder-PZN sind dann anzugeben, wenn Sie einen Bestandteil ohne tatsächliche PZN verwenden.
      </div>
    </div>
    <div class="c-fake-select h-width-100 p-r-xxl p-l-xxl p-l-xl">
      <div class="c-fake-select__content -m-l-s">09999005</div>
      <span class="c-fake-select__arrow">
        <b></b>
      </span>
  </div>
  </div>
</div>

Word Wrapping Demo

height: auto
height: auto
Show Code
html
<div class="h-flex h-space-between">
  <div class="h-width-30">
    <code>height: auto</code><br/>
    <div class="c-float-container -has-select -is-active">
      <label class="c-label" for="multiline">Multiline (Default)</label>
      <select class="js-select2" id="multiline" name="opts">
        <option value='1'>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. </option>
        <option value='2'>lorem ipsum dolor sit amet consectetur adipisici elit</option>
      </select>
    </div>
  </div>
  <div class="h-width-30">
    <code>height: auto</code>
    <select class="js-select2 demo-link-example"
            data-additional-classes="-is-link -small"
            name="link-select" id="link-select-small2">
      <option value="1">loremipsumdolorsitametconsecteturadipisicielit</option>
      <option value="0" class="js-option-no-lager">lorem ipsum dolor sit amet consectetur adipisici elit</option>
    </select>
  </div>
</div>

Settings and API

Show API and Settings
  • Form.init() to activate Floating Labels. See Forms Module.
  • Select.init() to apply default settings and initialize select2 on all js-select2 selects.

Use Select.apply($select, options); to apply your own options on a specific select-field. You can also extend the default options.

Available default options are:

  • Select.getDefaultOptions() @returns default settings for standard select-dropdowns
  • Select.getOptionsWithSearch() @returns extended settings for select-dropdowns with search
  • Select.getOptionsWithTags(unknownTerm) @returns extended settings for select-dropdowns with search and custom tags, @param {String} unknownTerm - optional parameter that describes the type of the "unknown custom tag" that is added

Vue Component: Combobox

Overview

INFO

Combobox is a searchable, accessible select field implemented as a Vue component. It renders a trigger button styled exactly like the .c-select fields above, and a teleported dropdown panel with a search input and a keyboard-navigable option list — all interaction (open/close, search, keyboard navigation, positioning) is implemented in Vue, with no jQuery/select2.js dependency.

When to use

Use Combobox instead of .js-select2 whenever you're building a Vue app and need a searchable dropdown driven by reactive data — e.g. filtering options as the user types by reacting to the search event (the component itself doesn't filter, it just emits the raw search value so you can update :options yourself, which also covers server-side/AJAX search), or letting the user type a value that isn't in the list (customOptions). For static, non-Vue pages, keep using .js-select2 as documented above.

Quick Start

Import

ts
import { Combobox } from '@pharma4u/patternlab/vue'

Basic usage

vue
<Combobox v-model="selectedItem" label="Item" :options="items" />

Positioning

Combobox positions its dropdown with @floating-ui/vue (^1.1.11), which is a regular dependency of patternlab — it's installed transitively, you don't need to add it to your own project.


Live Examples

Search Filtering (client-side)

Combobox does not filter its own option list — it only emits search with the typed text. Here we filter allItems ourselves in a computed and feed the result back via :options. The same @search handler could instead call an API and pass back a loading state, which is how it's used for server-side/AJAX search in production (labxpert-abfuellung's useRemoteComboboxSearch).

Show Code
vue
<script setup>
import { computed, ref } from 'vue'
import { Combobox } from '@pharma4u/patternlab/vue'

const value = ref(null)
const allItems = [
  { label: 'First item', value: '1' },
  { label: 'Second item', value: '2' },
  { label: 'Third item', value: '3' },
  { label: 'Fourth item', value: '4' },
  { label: 'Fifth item', value: '5' },
  { label: 'Sixth item', value: '6' },
  { label: 'Seventh item', value: '7' },
  { label: 'Eighth item', value: '8' },
  { label: 'Just an item', value: '9' },
  { label: 'Last item', value: '10' },
]

const filterTerm = ref('')
const filteredItems = computed(() => {
  const term = filterTerm.value.trim().toLowerCase()
  if (!term) return allItems
  return allItems.filter((option) => option.label.toLowerCase().includes(term))
})
</script>

<template>
  <Combobox
    v-model="value"
    label="Item (mit Filterung)"
    :options="filteredItems"
    no-results-text="Keine Einträge gefunden."
    @search="filterTerm = $event" />
</template>

Custom Options (free text)

With custom-options, typing a value that does not match any existing option adds it as a selectable "create new" entry.

Show Code
vue
<template>
  <Combobox
    v-model="selectedCustomItem"
    label="Item"
    :options="customItems.map(i => ({ label: i, value: i }))"
    custom-options
    custom-option-name="Neues Item" />
</template>

Error State

Show Code
vue
<template>
  <Combobox
    v-model="value"
    label="Pflichtfeld"
    :options="items"
    required
    error="Bitte wählen Sie einen Eintrag aus." />
</template>

Props

PropTypeDefaultDescription
modelValuestring | number | nullnullSelected value (v-model).
optionsSelectItem[] | Record<string, string>requiredFlat options ({label, value}[]), grouped options ({label, options}[]), or a plain value→label map.
selectedOptionsSelectItem[] | Record<string, string>[]Extra options used to resolve the display label for modelValue when it isn't present in options (e.g. lazily-loaded lists).
labelstringrequiredField label (from BaseInputFieldWithIconsProps).
placeholderstring'Bitte wählen ...'Text shown in the trigger when nothing is selected.
customOptionsbooleanfalseWhen true, typing a search value with no match offers it as a selectable custom option.
customOptionNamestring | nullnullLabel prefix shown for the generated custom option (also enables customOptions behavior on its own).
loadingbooleanfalseShows a spinner in the search field and suppresses the custom-option / empty-state logic while true.
noResultsTextstring'Keine Übereinstimmungen gefunden.'Text shown when options is empty.
idstringauto-generatedCustom ID for the trigger element.
hintstringundefinedHint text rendered below the field.
errorstringundefinedError message. When set, also forces the error validation state.
validationState'error' | 'warning' | 'success'undefinedExplicit validation state when no error message is set.
disabledbooleanfalseDisables the trigger.
requiredbooleanfalseShows the required marker (*) next to the label.
lightbooleanfalseLight visual variant of the field shell.
hiddenLabelbooleanfalseVisually hides the label (still available to assistive tech).
floatContainerbooleantrueWraps the field in the c-float-container layout.
containerClassstring | string[] | Record<string, boolean>''Extra class(es) for the field container.
iconLeft / iconRightstring''CSS class(es) for a left/right icon (ignored if the matching slot is used).
hasSmallIconbooleanfalseRenders the left icon in a smaller size.
leftIconInteractive / rightIconInteractivebooleanfalseRenders the icon outside the pointer-events-disabled wrapper so it can have its own click handler.

No built-in validation framework

Combobox does not integrate with any specific form/validation library. Drive error / validationState from whatever validation approach your app already uses.

Events

EventPayloadDescription
update:modelValuestring | number | nullEmitted on selection. Used by v-model.
select-itemSelectOption | nullEmitted alongside update:modelValue with the full selected option (label + value).
searchstringEmitted on every keystroke in the search field.
openEmitted when the dropdown opens.
closeEmitted when the dropdown closes.

Slots

SlotPropsDescription
leftIcon / rightIconReplace the icon markup generated from iconLeft / iconRight.
empty{ noResultsText }Replace the "no results" list item.
option{ option, index, selected, highlighted, customLabel }Replace the rendering of a single option row.

Accessibility

  • The trigger renders role="combobox" with aria-expanded, aria-controls, aria-invalid and aria-describedby.
  • The dropdown list renders role="listbox" / role="option" and keeps aria-selected in sync with the highlighted/selected option.
  • Keyboard support: ArrowDown / ArrowUp move the highlight, Enter selects, Escape closes.
  • The search input is auto-focused once the dropdown has finished positioning.
  • Clicking outside the trigger and panel closes the dropdown (via a document-level mousedown listener that is added/removed with the open state).

Notes

  • The dropdown panel is rendered via <Teleport to="body"> and positioned with @floating-ui/vue (flip + shift + autoUpdate), matching the trigger's width and flipping above it when there isn't enough room below.
  • Combobox is composed from smaller, individually exported pieces: BaseInputField (generic field shell), ComboboxPanel, ComboboxOptions, ComboboxSearch, and the useComboboxOptions composable — all available from @pharma4u/patternlab/vue if you need to build a custom variant.