Svelte Select。一个适用于 Svelte 的选择组件
Examples of every prop, callback, snippet and more
npm install svelte-select
svelte-select v6+ requires Svelte 5. The component uses runes, callback props instead of createEventDispatcher, and snippet props instead of named slots.
If you are upgrading from an older version, see the migration guide.
List position and floating is powered by floating-ui, see their package-entry-points docs if you encounter build errors.
| Prop | Type | Default | Description |
|---|---|---|---|
| items | any[] |
[] |
Array of items available to display / filter |
| value | any |
undefined |
Selected value(s). Shape depends on valueMode — see below. |
| valueMode | string |
item |
item: full item object(s). id: primitive id(s) via itemId. String/primitive items keep primitive value without setting id. |
| itemId | string |
value |
Override default identifier |
| label | string |
label |
Override default label |
| id | string |
null |
id attr for input field |
| filterText | string |
'' |
Text to filter items by |
| placeholder | string |
Please select |
Placeholder text |
| hideEmptyState | boolean |
false |
When no items hide list |
| listOpen | boolean |
false |
Open/close list |
| class | string |
'' |
container classes |
| containerStyles | string |
'' |
Add inline styles to container |
| clearable | boolean |
true |
Enable clearing of value(s) |
| disabled | boolean |
false |
Disable select |
| multiple | boolean |
false |
Enable multi-select |
| searchable | boolean |
true |
If false search/filtering is disabled |
| groupHeaderSelectable | boolean |
false |
Enable selectable group headers |
| focused | boolean |
false |
Controls input focus |
| listAutoWidth | boolean |
true |
If false will ignore width of select |
| showChevron | boolean |
false |
Show chevron |
| inputAttributes | object |
{} |
Pass in HTML attributes to Select's input |
| placeholderAlwaysShow | boolean |
false |
When multiple placeholder text will always show |
| loading | boolean |
false |
Shows loading-icon. loadOptions will override this |
| listOffset | number |
5 |
px space between select and list |
| debounceWait | number |
300 |
milliseconds debounce wait |
| floatingConfig | object |
{} |
Floating UI Config |
| hasError | boolean |
false |
If true sets error class and styles |
| name | string |
null |
Name attribute of hidden input, helpful for form actions |
| required | boolean |
false |
If Select is within a `` will restrict form submission |
| multiFullItemClearable | boolean |
false |
When multiple selected items will clear on click |
| closeListOnChange | boolean |
true |
After onchange list will close |
| clearFilterTextOnBlur | boolean |
true |
If false, filterText value is preserved on blur |
These props support two-way binding: value, filterText, items, loading, listOpen, focused, hoverItemIndex, container, and input.
Customize parts of the select by passing snippet props. Kebab-case slot names from v4 map to camelCase snippet names (for example clear-icon → clearIcon, list-prepend → listPrepend). The required slot is now requiredIndicator to avoid clashing with the required prop.
{#snippet prepend()}{/snippet}
{#snippet selection({ selection, index })}{/snippet}
{#snippet clearIcon()}{/snippet}
{#snippet multiClearIcon()}{/snippet}
{#snippet loadingIcon()}{/snippet}
{#snippet chevronIcon({ listOpen })}{/snippet}
{#snippet listPrepend()}{/snippet}
{#snippet list({ filteredItems })}{/snippet}
{#snippet listAppend()}{/snippet}
{#snippet item({ item, index })}{/snippet}
{#snippet empty()}{/snippet}
{#snippet inputHidden({ value })}{/snippet}
{#snippet requiredIndicator({ value })}{/snippet}
Pass functions as props to respond to select behaviour. Callbacks receive their payload directly.
| Callback | Payload | Description |
|---|---|---|
| onchange | value |
Fires when the user selects an option |
| oninput | value |
Fires when the bound value changes |
| onselect | selection |
Fires with the selected item when an option is chosen |
| onfocus | FocusEvent |
Fires when the select input receives focus |
| onblur | FocusEvent |
Fires when the select input loses focus |
| onclear | value or removed item |
Fires when clear is invoked or an item is removed from a multi select |
| onloaded | { items } |
Fires when loadOptions resolves |
| onerror | { type, details } |
Fires when an error is caught (for example a rejected loadOptions) |
| onfilter | filteredItems |
Fires when listOpen: true and items are filtered |
| onhoverItem | hoverItemIndex |
Fires when the hovered list item index changes |
items can be simple arrays or collections.
They can also be grouped and include non-selectable items.
valueMode controls what shape bind:value uses. It must match how you pass value and how your items identify options (itemId, default 'value').
| Mode | value (single) |
value (multiple) |
On select |
|---|---|---|---|
item (default) |
item object | item object[] | list item |
id |
primitive id | primitive id[] | item[itemId] only |
item — value is the full row. Use with object items. Labels come from value.label (or label prop).id — value is just the identifier. Use for forms/APIs when items are objects. Labels are resolved from items by matching itemId.String / primitive items: when items is a string (or other primitive) array, value stays a matching primitive automatically — you do not need valueMode="id". On select, value is not upgraded to { value, label }.
For object items, value and valueMode must align — the component does not convert between shapes. Object items with valueMode="id" means value should be 'cake', not { value: 'cake', label: 'Cake' }.
You can also use custom collections.
To load items asynchronously then loadOptions is the simplest solution. Supply a function that returns a Promise that resolves with a list of items. loadOptions has debounce baked in and fires each time filterText is updated.
svelte-select uses floating-ui to control the list floating. See their docs and pass in your config via the floatingConfig prop.
These props and methods are exposed for advanced customization. See test/src/tests.js for examples.
Override filtering, grouping, or async loading:
label.toLowerCase().includes(filterText.toLowerCase())}
groupBy={(item) => item.group}
groupFilter={(groups) => groups}
createGroupHeaderItem={(groupValue) => ({ value: groupValue, label: groupValue })}
loadOptions={async (filterText) => []}
debounce={(fn, wait = 1) => setTimeout(fn, wait)}
filter={customFilter}
getItems={customGetItems}
/>
Imperative methods (via bind:this):
// Returns the current filtered list items
getFilteredItems();
// Clears the current value and focuses the input
handleClear();
loadOptions must return a Promise that resolves with a list of items. Return { cancelled: true } to keep the loading state active.
Core replaceable helpers live in get-items.js and filter.js.
Override these props to change the aria-context and aria-selection text.
`Option ${values}, selected.`}
ariaListOpen={(label, count) =>
`You are currently focused on option ${label}. There are ${count} results available.`}
ariaFocused={() => `Select is focused, type to refine list, press down to open the menu.`}
/>
You can style a component by overriding the available CSS custom properties.
You can also use the inputStyles prop to write in any override styles needed for the input.
If you'd like to supply your own styles use: import Select from 'svelte-select/no-styles'. Then somewhere in your code or build pipeline add your own. There is a tailwind stylesheet via import 'svelte-select/tailwind.css'. It uses @extend so PostCSS is required.
暂无开放 Issues,或尚未同步最近议题。