Select

<wa-select> Since 2.0 stable

Selects allow you to choose items from a menu of predefined options.

Option 1 Option 2 Option 3 Option 4 Option 5 Option 6
<wa-select>
  <wa-option value="option-1">Option 1</wa-option>
  <wa-option value="option-2">Option 2</wa-option>
  <wa-option value="option-3">Option 3</wa-option>
  <wa-option value="option-4">Option 4</wa-option>
  <wa-option value="option-5">Option 5</wa-option>
  <wa-option value="option-6">Option 6</wa-option>
</wa-select>

        

This component works with standard <form> elements. Please refer to the section on form controls to learn more about form submission and client-side validation.

Examples

Labels

Use the label attribute to give the select an accessible label. For labels that contain HTML, use the label slot instead.

Option 1 Option 2 Option 3
<wa-select label="Select one">
  <wa-option value="option-1">Option 1</wa-option>
  <wa-option value="option-2">Option 2</wa-option>
  <wa-option value="option-3">Option 3</wa-option>
</wa-select>

        

Hint

Add descriptive hint to a select with the hint attribute. For hints that contain HTML, use the hint slot instead.

Novice Intermediate Advanced
<wa-select label="Experience" hint="Please tell us your skill level.">
  <wa-option value="1">Novice</wa-option>
  <wa-option value="2">Intermediate</wa-option>
  <wa-option value="3">Advanced</wa-option>
</wa-select>

        

Placeholders

Use the placeholder attribute to add a placeholder.

Option 1 Option 2 Option 3
<wa-select placeholder="Select one">
  <wa-option value="option-1">Option 1</wa-option>
  <wa-option value="option-2">Option 2</wa-option>
  <wa-option value="option-3">Option 3</wa-option>
</wa-select>

        

Clearable

Use the with-clear attribute to make the control clearable. The clear button only appears when an option is selected.

Option 1 Option 2 Option 3
<wa-select with-clear value="option-1">
  <wa-option value="option-1">Option 1</wa-option>
  <wa-option value="option-2">Option 2</wa-option>
  <wa-option value="option-3">Option 3</wa-option>
</wa-select>

        

Appearance

Use the appearance attribute to change the select's visual appearance.

Option 1 Option 2 Option 3
<wa-select appearance="filled">
  <wa-option value="option-1">Option 1</wa-option>
  <wa-option value="option-2">Option 2</wa-option>
  <wa-option value="option-3">Option 3</wa-option>
</wa-select>

        

Pill

Use the pill attribute to give selects rounded edges.

Option 1 Option 2 Option 3
<wa-select pill>
  <wa-option value="option-1">Option 1</wa-option>
  <wa-option value="option-2">Option 2</wa-option>
  <wa-option value="option-3">Option 3</wa-option>
</wa-select>

        

Disabled

Use the disabled attribute to disable a select.

Option 1 Option 2 Option 3
<wa-select placeholder="Disabled" disabled>
  <wa-option value="option-1">Option 1</wa-option>
  <wa-option value="option-2">Option 2</wa-option>
  <wa-option value="option-3">Option 3</wa-option>
</wa-select>

        

Multiple

To allow multiple options to be selected, use the multiple attribute. It's a good practice to use with-clear when this option is enabled. You can select multiple options by adding the selected attribute to individual options.

Option 1 Option 2 Option 3 Option 4 Option 5 Option 6
<wa-select label="Select a Few" multiple with-clear>
  <wa-option value="option-1" selected>Option 1</wa-option>
  <wa-option value="option-2" selected>Option 2</wa-option>
  <wa-option value="option-3" selected>Option 3</wa-option>
  <wa-option value="option-4">Option 4</wa-option>
  <wa-option value="option-5">Option 5</wa-option>
  <wa-option value="option-6">Option 6</wa-option>
</wa-select>

        

Selecting multiple options may result in wrapping, causing the control to expand vertically. You can use the max-options-visible attribute to control the maximum number of selected options to show at once.

Setting Initial Values

Use the selected attribute on individual options to set the initial selection, similar to native HTML.

Option 1 Option 2 Option 3 Option 4
<wa-select>
  <wa-option value="option-1" selected>Option 1</wa-option>
  <wa-option value="option-2">Option 2</wa-option>
  <wa-option value="option-3">Option 3</wa-option>
  <wa-option value="option-4">Option 4</wa-option>
</wa-select>

        

For multiple selections, apply it to all selected options.

Option 1 Option 2 Option 3 Option 4
<wa-select multiple with-clear>
  <wa-option value="option-1" selected>Option 1</wa-option>
  <wa-option value="option-2" selected>Option 2</wa-option>
  <wa-option value="option-3">Option 3</wa-option>
  <wa-option value="option-4">Option 4</wa-option>
</wa-select>

        

Framework users can bind directly to the value property for reactive data binding and form state management.

Grouping Options

Use <wa-divider> to group listbox items visually. You can also use <small> to provide labels, but they won't be announced by most assistive devices.

Section 1 Option 1 Option 2 Option 3 Section 2 Option 4 Option 5 Option 6
<wa-select>
  <small>Section 1</small>
  <wa-option value="option-1">Option 1</wa-option>
  <wa-option value="option-2">Option 2</wa-option>
  <wa-option value="option-3">Option 3</wa-option>
  <wa-divider></wa-divider>
  <small>Section 2</small>
  <wa-option value="option-4">Option 4</wa-option>
  <wa-option value="option-5">Option 5</wa-option>
  <wa-option value="option-6">Option 6</wa-option>
</wa-select>

        

Sizes

Use the size attribute to change a select's size. Note that size does not apply to listbox options.

Option 1 Option 2 Option 3
Option 1 Option 2 Option 3
Option 1 Option 2 Option 3
<wa-select placeholder="Small" size="small">
  <wa-option value="option-1">Option 1</wa-option>
  <wa-option value="option-2">Option 2</wa-option>
  <wa-option value="option-3">Option 3</wa-option>
</wa-select>

<br />

<wa-select placeholder="Medium" size="medium">
  <wa-option value="option-1">Option 1</wa-option>
  <wa-option value="option-2">Option 2</wa-option>
  <wa-option value="option-3">Option 3</wa-option>
</wa-select>

<br />

<wa-select placeholder="Large" size="large">
  <wa-option value="option-1">Option 1</wa-option>
  <wa-option value="option-2">Option 2</wa-option>
  <wa-option value="option-3">Option 3</wa-option>
</wa-select>

        

Placement

The preferred placement of the select's listbox can be set with the placement attribute. Note that the actual position may vary to ensure the panel remains in the viewport. Valid placements are top and bottom.

Option 1 Option 2 Option 3
<wa-select placement="top">
  <wa-option value="option-1">Option 1</wa-option>
  <wa-option value="option-2">Option 2</wa-option>
  <wa-option value="option-3">Option 3</wa-option>
</wa-select>

        

Start & End Decorations

Use the start and end slots to add presentational elements like <wa-icon> within the combobox.

Option 1 Option 2 Option 3
Option 1 Option 2 Option 3
Option 1 Option 2 Option 3
<wa-select placeholder="Small" size="small" with-clear>
  <wa-icon slot="start" name="house" variant="solid"></wa-icon>
  <wa-icon slot="end" name="flag-checkered"></wa-icon>
  <wa-option value="option-1">Option 1</wa-option>
  <wa-option value="option-2">Option 2</wa-option>
  <wa-option value="option-3">Option 3</wa-option>
</wa-select>
<br />
<wa-select placeholder="Medium" size="medium" with-clear>
  <wa-icon slot="start" name="house" variant="solid"></wa-icon>
  <wa-icon slot="end" name="flag-checkered"></wa-icon>
  <wa-option value="option-1">Option 1</wa-option>
  <wa-option value="option-2">Option 2</wa-option>
  <wa-option value="option-3">Option 3</wa-option>
</wa-select>
<br />
<wa-select placeholder="Large" size="large" with-clear>
  <wa-icon slot="start" name="house" variant="solid"></wa-icon>
  <wa-icon slot="end" name="flag-checkered"></wa-icon>
  <wa-option value="option-1">Option 1</wa-option>
  <wa-option value="option-2">Option 2</wa-option>
  <wa-option value="option-3">Option 3</wa-option>
</wa-select>

        

Custom Tags

When multiple options can be selected, you can provide custom tags by passing a function to the getTag property. Your function can return a string of HTML, a Lit Template, or an HTMLElement. The getTag() function will be called for each option. The first argument is an <wa-option> element and the second argument is the tag's index (its position in the tag list).

Remember that custom tags are rendered in a shadow root. To style them, you can use the style attribute in your template or you can add your own parts and target them with the ::part() selector.

Email Phone Chat
<wa-select placeholder="Select one" multiple with-clear class="custom-tag">
  <wa-option value="email" selected>
    <wa-icon slot="start" name="envelope" variant="solid"></wa-icon>
    Email
  </wa-option>
  <wa-option value="phone" selected>
    <wa-icon slot="start" name="phone" variant="solid"></wa-icon>
    Phone
  </wa-option>
  <wa-option value="chat">
    <wa-icon slot="start" name="comment" variant="solid"></wa-icon>
    Chat
  </wa-option>
</wa-select>

<script type="module">
  await customElements.whenDefined('wa-select');
  const select = document.querySelector('.custom-tag');
  await select.updateComplete;

  select.getTag = (option, index) => {
    // Use the same icon used in wa-option
    const name = option.querySelector('wa-icon[slot="start"]').name;

    // You can return a string, a Lit Template, or an HTMLElement here
    return `
      <wa-tag with-remove>
        <wa-icon name="${name}" style="padding-inline-end: .5rem;"></wa-icon>
        ${option.label}
      </wa-tag>
    `;
  };
</script>

        

Be sure you trust the content you are outputting! Passing unsanitized user input to getTag() can result in XSS vulnerabilities.

Lazy loading options

Lazy loading options works similarly to native <select> elements. The select component handles various scenarios intelligently:

Basic lazy loading scenarios:

Here's a comprehensive example showing different lazy loading scenarios:

Bar Baz
Add "foo" option


Add "foo" option

Bar Baz
Add "foo" option (selected)


Add "foo" option


Reset Show FormData


<form id="lazy-options-example">
  <div>
    <wa-select name="select-1" value="foo" label="Single select (with existing options)">
      <wa-option value="bar">Bar</wa-option>
      <wa-option value="baz">Baz</wa-option>
    </wa-select>
    <br />
    <wa-button type="button">Add "foo" option</wa-button>
  </div>

  <br />

  <div>
    <wa-select name="select-2" value="foo" label="Single select (with no existing options)"> </wa-select>
    <br />
    <wa-button type="button">Add "foo" option</wa-button>
  </div>

  <br />

  <div>
    <wa-select name="select-3" multiple label="Multiple Select (with existing selected options)">
      <wa-option value="bar" selected>Bar</wa-option>
      <wa-option value="baz" selected>Baz</wa-option>
    </wa-select>
    <br />
    <wa-button type="button">Add "foo" option (selected)</wa-button>
  </div>

  <br />

  <div>
    <wa-select name="select-4" value="foo" multiple label="Multiple Select (with no existing options)"> </wa-select>
    <br />
    <wa-button type="button">Add "foo" option</wa-button>
  </div>

  <br /><br />

  <div style="display: flex; gap: 16px;">
    <wa-button type="reset">Reset</wa-button>
    <wa-button type="submit" variant="brand">Show FormData</wa-button>
  </div>

  <br />

  <pre hidden><code id="lazy-options-example-form-data"></code></pre>

  <br />
</form>

<script type="module">
  function addFooOption(e) {
    const addFooButton = e.target.closest("wa-button[type='button']");
    if (!addFooButton) {
      return;
    }
    const select = addFooButton.parentElement.querySelector('wa-select');

    if (select.querySelector("wa-option[value='foo']")) {
      // Foo already exists. no-op.
      return;
    }

    const option = document.createElement('wa-option');
    option.setAttribute('value', 'foo');
    option.innerText = 'Foo';

    // For the multiple select with existing selected options, make the new option selected
    if (select.getAttribute('name') === 'select-3') {
      option.selected = true;
    }

    select.append(option);
  }

  function handleLazySubmit(event) {
    event.preventDefault();

    const formData = new FormData(event.target);
    const codeElement = document.querySelector('#lazy-options-example-form-data');

    const obj = {};
    for (const key of formData.keys()) {
      const val = formData.getAll(key).length > 1 ? formData.getAll(key) : formData.get(key);
      obj[key] = val;
    }

    codeElement.textContent = JSON.stringify(obj, null, 2);

    const preElement = codeElement.parentElement;
    preElement.removeAttribute('hidden');
  }

  const container = document.querySelector('#lazy-options-example');
  container.addEventListener('click', addFooOption);
  container.addEventListener('submit', handleLazySubmit);
</script>

        

The key principle is that the select component prioritizes user interactions and explicit selections over programmatic changes, ensuring a predictable user experience even with dynamically loaded content.

Slots

Learn more about using slots.

Name Description
(default) The listbox options. Must be <wa-option> elements. You can use <wa-divider> to group items visually.
label The input's label. Alternatively, you can use the label attribute.
start An element, such as <wa-icon>, placed at the start of the combobox.
end An element, such as <wa-icon>, placed at the end of the combobox.
clear-icon An icon to use in lieu of the default clear icon.
expand-icon The icon to show when the control is expanded and collapsed. Rotates on open and close.
hint Text that describes how to use the input. Alternatively, you can use the hint attribute.

Attributes & Properties

Learn more about attributes and properties.

Name Description Reflects
validationTarget
Where to anchor native constraint validation
name
name
The name of the select, submitted as a name/value pair with form data.
Type string
Default ''
value
value
The select's value. This will be a string for single select or an array for multi-select.
size
size
The select's size.
Type 'small' | 'medium' | 'large'
Default 'medium'
placeholder
placeholder
Placeholder text to show as a hint when the select is empty.
Type string
Default ''
multiple
multiple
Allows more than one option to be selected.
Type boolean
Default false
maxOptionsVisible
max-options-visible
The maximum number of selected options to show when multiple is true. After the maximum, "+n" will be shown to indicate the number of additional items that are selected. Set to 0 to remove the limit.
Type number
Default 3
disabled
disabled
Disables the select control.
Type boolean
Default false
withClear
with-clear
Adds a clear button when the select is not empty.
Type boolean
Default false
open
open
Indicates whether or not the select is open. You can toggle this attribute to show and hide the menu, or you can use the show() and hide() methods and this attribute will reflect the select's open state.
Type boolean
Default false
appearance
appearance
The select's visual appearance.
Type 'filled' | 'outlined'
Default 'outlined'
pill
pill
Draws a pill-style select with rounded edges.
Type boolean
Default false
label
label
The select's label. If you need to display HTML, use the label slot instead.
Type string
Default ''
placement
placement
The preferred placement of the select's menu. Note that the actual placement may vary as needed to keep the listbox inside of the viewport.
Type 'top' | 'bottom'
Default 'bottom'
hint
hint
The select's hint. If you need to display HTML, use the hint slot instead.
Type string
Default ''
withLabel
with-label
Used for SSR purposes when a label is slotted in. Will show the label on first render.
Type boolean
Default false
withHint
with-hint
Used for SSR purposes when hint is slotted in. Will show the hint on first render.
Type boolean
Default false
form
form
By default, form controls are associated with the nearest containing <form> element. This attribute allows you to place the form control outside of a form and associate it with the form that has this id. The form must be in the same document or shadow root for this to work.
Type null
Default null
required
required
The select's required attribute.
Type boolean
Default false
getTag
A function that customizes the tags to be rendered when multiple=true. The first argument is the option, the second is the current tag's index. The function should return either a Lit TemplateResult or a string containing trusted HTML of the symbol to render at the specified value.
Type (option: WaOption, index: number) => TemplateResult | string | HTMLElement

Methods

Learn more about methods.

Name Description Arguments
show() Shows the listbox.
hide() Hides the listbox.
focus() Sets focus on the control. options: FocusOptions
blur() Removes focus from the control.

Events

Learn more about events.

Name Description
input Emitted when the control receives input.
change Emitted when the control's value changes.
focus Emitted when the control gains focus.
blur Emitted when the control loses focus.
wa-clear Emitted when the control's value is cleared.
wa-show Emitted when the select's menu opens.
wa-after-show Emitted after the select's menu opens and all animations are complete.
wa-hide Emitted when the select's menu closes.
wa-after-hide Emitted after the select's menu closes and all animations are complete.
wa-invalid Emitted when the form control has been checked for validity and its constraints aren't satisfied.

CSS custom properties

Learn more about CSS custom properties.

Name Description
--tag-max-size
When using multiple, the max size of tags before their content is truncated.
Default 10ch

Custom States

Learn more about custom states.

Name Description CSS selector
blank The select is empty. :state(blank)

CSS parts

Learn more about CSS parts.

Name Description
form-control The form control that wraps the label, input, and hint.
form-control-label The label's wrapper.
form-control-input The select's wrapper.
hint The hint's wrapper.
combobox The container the wraps the start, end, value, clear icon, and expand button.
start The container that wraps the start slot.
end The container that wraps the end slot.
display-input The element that displays the selected option's label, an <input> element.
listbox The listbox container where options are slotted.
tags The container that houses option tags when multiselect is used.
tag The individual tags that represent each multiselect option.
tag__content The tag's content part.
tag__remove-button The tag's remove button.
tag__remove-button__base The tag's remove button base part.
clear-button The clear button.
expand-icon The container that wraps the expand icon.

Dependencies

This component automatically imports the following elements. Sub-dependencies, if any exist, will also be included in this list.

Importing

The autoloader is the recommended way to import components. If you prefer to do it manually, use one of the following code snippets.

CDN npm React

To manually import this component from the CDN, use the following code.

import 'https://early.webawesome.com/[email protected]/dist/components/select/select.js';
        

To manually import this component from NPM, use the following code.

import '@awesome.me/webawesome/dist/components/select/select.js';
        

To manually import this component from React, use the following code.

import '@awesome.me/webawesome/dist/react/select';
        
Need a hand? Report a bug Ask for help
    No results