Svelecte provide basically every (hopefully) common functionality, you would expect from autocomplete/select/multiselect component. It's main inspiration was selectize.js.

Current version: svelecte version


Features
  • searchable
  • multiselect with limit of max selected items
  • allow simple array or complex objects as items
  • custom item renderer (formatter)
  • allow creating new items
  • remote data fetch
  • virtual list support
  • usable as custom element
  • i18n support
  • SSR support
  • lazy dropdown rendering
  • stylable
  • reordable multi selection with addition of svelte-dnd-action. See example.

Getting started

Svelecte can be used in your Svelte app or used as a standalone custom element. MDN link about custom elements.

Check playground example for all options

Install from npm
npm install svelecte --save

• Basic Usage •

Related properties:
options: array
Array of items. Svelecte support plain or object array as options property. By default it converts plain string items to object with value and label properties.
valueField: string|null
Specify which property is used as value. This value is returned as value. If not specified, property will be resolved automatically.
labelField: string|null
Specify which property should be shown. If not specified, property will be resolved automatically.
name: string
When defined, corresponding <select> is created. So it can be used in forms automatically.
multiple: bool
Toggle multiselection. Check playground example.
Exposed selection properties:
bind:value:array|mixed|null
It returns valueField property / array like in normal selects or object / object array depending whether valueAsObject property is set.
Selection is always an array, when multiple is set to true.
bind:readSelection:array|object|null
Is readonly property. Return selected object / array of objects
Show code

              

Example of plain array options and variable value output:

Related properties:
labelAsValue: bool
For plain array options you can also specify if you are interested in value or label property by setting labelAsValue property to true.
Show code

              

• Option groups •

Optgroups are defined as objects with label and options properties. These properties are customizable.

Related properties:
groupLabelField: string
Which object property act as optgroup label.
groupItemsField: string
Which object property act as optgroup list (containing real options).

Optgroup labels are customizable by styling .optgroup-header class.

Show code

              

• Custom item rendering •

You can define custom renderer function, which takes current option and return HTML string. Your renderer can display selected items differently due second function argument.

Related properties:
renderer: string | fn(item : object|string, isSelected: bool, inputValue: string) -> string
If string is passed, context renderer with given name is being used. You can add new renderers through context function addFormatter(name: string, formatFn: function). formatFn function can expect arguments specified above.

By default labelField is used to render visible text.

disableHighlight: bool
Disable highlighting of input value in results. Can be useful with a renderer function that includes additional text or does its own highlighting.

If renderer property is not enough for you or you prefer Component syntax to HTML strings, you can use your own Components. Keep in mind that default highlighting when searching, but the rest of features like styling should be inherited if you use proper css classes (the same as Item component).

To make it easier to use your own Components, there are available actions, highlighting function and close button icon for you to use.

The simplest example can be found in this REPL.

Show code

              

• Icon slot •

You can provide icon by defining icon slot content

Show code

              

• Remote datasource •

Sometimes can be useful, especially in fetch mode, when entered text stays even when input loses focus. And by default when input is empty, fetched results (if fetched based on search input) are cleared.
Related properties:
fetch: string|null
string specifying remote endpoint, ie: https://example.com/url?search=[query]
fetchMode: string
init - remote dataset is fetched immediately upon setting, searching is conducted only among available items. Fetch fallbacks to init also when fetch is string and [query] placeholder is not specified.
auto - remote search query is triggered when typing, but it expects [query] placeholder in fetch property. This is default value.
fetchCallback: ?fn(jsonResponse: object): array
Response transform function. It contains JSON-ized response. If not specified, one of following properties are tried in given order: data, items, options or response JSON itself as a fallback.
fetchResetOnBlur: bool
Reset previous search results on empty input.
minQuery: number
Force minimal length of input text to trigger remote request.
disableSifter: bool
Can be disabled (especially with fetch) when further filtering or sorting may be undesired (due to server-side sorting & and filtering based on user input).
Show code

              

Use Svelecte as custom element (CE)

When including Svelecte in your app, you can import what parts do you need...

import { registerSvelecte, addFormatter, config } from 'svelecte/component';

... or download the latest version manually from GitHub.

<link rel="stylesheet" href="https://unpkg.com/svelecte-element/dist/svelecte.css">
<script src="https://unpkg.com/svelecte/dist/svelecte-element.js">/script>

Standalone version offer same properties as module version:

const { registerSvelecte, addFormatter, config } = window.Svelecte;

• Setup component •

Registering custom element is mandatory step. Use registerSvelecte function for that. Also when using CE version, you can define additional renderer functions by calling addFormatter function (check Custom item rendering section) or update global config.

// You can use your own component name. If not specified, `el-svelecte` will be used.
registerSvelecte();

// after registering, given HTML tag will render as Svelecte component
<el-svelecte ...properties></el-svelecte>

// add additional renderers
addFormatter('caps', item => item.text.toUpperCase());

// additionally change global config defaults
config.clearable = true;
Component reactive API

By reactive API I mean properties that dynamically changes Svelecte inner logic. Not all attributes are reactive. For example parent prop is not reactive and is not even accessible programmatically.
Reactive API for custom element is accessible programmatically or directly through element's attributes. Almost all Option props are mirrored.

List of reactive properties follows:

const OPTION_LIST = [
  'options', 'value',
  // form-related
  'name', 'required', 'disabled',
  // basic
  'value-field', 'label-field', 'disabled-field', 'placeholder',
  // UI, UX
  'searchable', 'clearable', 'renderer', 'disable-highlight', 'select-on-tab', 'reset-on-blur',
  // multiple
  'multiple', 'max', 'collapse-selection',
  // creating
  'creatable', 'creatablePrefix', 'allow-editing', 'keepCreated', 'delimiter',
  // remote
  'fetch', 'fetch-reset-on-blur', 'min-query',
  // perf & virtual list
  'lazy-dropdown', 'virtual-list', 'vl-height', 'vl-item-size',
  // sifter
  'search-field', 'sort-field', 'disable-sifter',
  // others
  'label-as-value'
];
Restrictions

renderer property supports only string values.
lazy-dropdown is settable only during component initialization

• Basic example with custom elements •

Simple example that enables you to insert multiple el-svelecte DOM elements.
Check onSubmit function in example code.

Custom-element version has one specific feature. You can decide if you want to trigger change event when programmatically setting value:

element.value = 'changedValue';            // doesn't trigger change event

When you want to trigger change event, you need to use emitChange modifier before setting new value:

element.emitChange.value = 'changedValue'; // DOES trigger change event
Show code

                

• Wired (dependent) selects •

Quite common scenario when one select (child) depends on another (parent) and when parent is selected, you need to fetch data child dataset. Svelecte supports this use-case directly.

Related DOM attributes (on child select):
parent: string
DOM id property of parent select. This attribute should be defined on child svelecte element.
Note that child is disabled automatically when parent has no selection.
fetch: string
When defining fetch property on child select, specify [parent] placeholder, which will contain value from parent select when selected.
You can also combine [parent] and [query] placeholder.
Show code

                

Remote (ajax) datasource

Show code

                

• Usage with Vue.js •

It is very easy to use Svelecte with Vue.js. You only need to add Svelecte element to ignoredElements for Vue 2 or handle in in isCustomElement in Vue 3.
The only thing you need to handle is listening to change as you would with native inputs.

Show code

                

Options

Property Type Default Description
options array [] Data array
valueAsObject bool false Switch whether Svelecte should expects from and return to bind:value objects or primitive value (usually string, number)
valueField string null Property to be used as value (if not specified, will be selected automatically)
labelField string null Property shown in dropdown (if not specified, will be selected automatically)
groupLabelField string label Property defining optgroup header
groupItemsField string options Property holding optgroup option list
disabledField string $disabled Property upon which is determined, whether given option is selectable or not
name string null Create <select>, usable for normal forms.
inputId string null id attribute of input element. Useful, when you want to have input selectable by clicking on the label
required bool false This property is passed to generated <select> element. Make sense only when name is defined
placeholder string Select Input placeholder
searchable bool true Allow search among items by typing
disabled bool false Disable component
renderer string|function null Dropdown and selection renderer function. More info in item rendering section
controlItem Component Item Item component when item is selected. See README section on GitHub for more details
dropdownItem Component Item Item component when item is selected. See README section on GitHub for more details
selectOnTab bool false Allow selecting currently active item by Tab key
resetOnBlur bool true Control if input value should be cleared on blur
resetOnSelect bool true Control if input value should be cleared on item selection. Note: Applicable only with multiple
clearable bool false Display ✖ icon to clear whole selection
multiple bool false allow multiselection. Will be set automatically to true, if name property ends with [], like tags[]
max number 0 Maximum allowed items selected, applicable only for multiselect
collapseSelection bool false collapse selection when multiple and not focused
anchor string null existing select (for CE)
creatable bool false Allow creating new item(s)
creatablePrefix string * Prefix marking new item
allowEditing bool false When pressing Backspace switch to edit mode instead of removing newly created item. NOTE: intended to be used with creatable property.
keepCreated bool true Switch whether to add newly created option to option list or not
delimiter string , Split inserted text when pasting to create multiple items
createFilter function null Function, that transform input string to custom value. It can serve as a filter, if value is valid or not. If you want to dismiss entered value, function should return '' (empty string). By default all input string is trimmed and all multiple spaces are removed. Function notation:
createFilter(inputValue: string, dropdownOptions: array): string
createTransform function null Custom function transforming input string to option object. By default it just sets value as output from createFilter and label as output from createFilter prefixed with creatablePrefix property. Function notation:
createTransform(inputValue: string, creatablePrefix: string, valueField: string, labelField: string): object
fetch string|function null Check "remote datasource" section for more details
fetchMode string auto When set to init options are fetched only when mounted, when searching it search in downloaded dataset
fetchCallback function null Optional fetch callback
fetchResetOnBlur bool true Reset previous search results on empty input, related to resetOnBlur
minQuery number 1 Minimal amount of characters required to perform remote request. Valid only in combination with fetch defined
disableSifter bool false Can be disabled (especially with fetch) when further filtering or sorting may be undesired (due to server-side sorting & and filtering based on user input).
lazyDropdown bool true Dropdown is rendered only after first focus, not by default
virtualList bool false Whether use virtual list for dropdown items (useful for large datasets)
vlHeight number null Height of virtual list dropdown (if not specified, computed automatically)
vlItemSize number null Height of one row (if not specified, computed automatically)
searchField string|array null Specify item property that will be used to search by (if not specified all props except value prop will be used)
sortField string null Specify sort property. If not specified, first after value field will be used
class string 'svelecte-control' Default css class
style string null Inline style
i18n object null Overriding object for i18n properties
dndzone function empty function If you pass dndzone from svelte-dnd-action, reordering of selected items will be possible. See example REPL how to set it up.
validatorAction array null Designed to be used with svelte-use-form. Pass validators function as a first item, and validators as the rest. See example REPL.

Events

Event parameter description
fetch array newly fetched remote options
change object|array|null selected objects. If anchor <select> is defined, change event is called also on it
createoption object newly created option object
blur - normal blur event
invalidValue mixed (invalid value) triggered when passed value is out of provided options items. Internal value is always set to null.

API

Name type arguments description
focus function - focus input
getSelection function bool return selection, if true is passed, only values are returns, whole objects otherwise
setSelection function array, bool set selection programmatically, toggle for emitting change event. (Can be desirable for custom-element)
config property - context property: global common config for all instances, you can override most properties here and also some additional, mainly i18n
addFormatter function - context function: with signature (name, formatFn) you can add additional item renderers (formatters). More details in Custom rendering example

Localization

Localization can be overridden globally and on component level.

/** default values */
{
  /** rest omitted for brevity */
  i18n: {
    empty: 'No options',
    nomatch: 'No matching options',    
    max: num => `Maximum items ${num} selected`,
    fetchBefore: 'Type to search',
    fetchQuery: minQuery => `Type ${minQuery > 1 ? `at least ${minQuery} characters ` : '' }to search`,
    fetchEmpty: 'No data related to your search',
    collapsedSelection: count => `${count} selected`,
    createRowLabel: value => `Create '${value}'`
  },
  collapseSelectionFn: function(selectionCount, selection) {
    return settings.i18n.collapsedSelection(selectionCount);
  }
}

For global override, import config and update according to your needs. Don't forget that max, collapsedSelection and createRowLabel are functions. You can also override only specific keys if you need to.

import Svelecte, { config } from 'svelecte';

// global override
config.i18n = {
  /** here replace all keys.*/
}
// local override (component-level)
const myI18n = {
    empty: `Empty list, can't you see?`
}

<Svelecte i18n={myI18n}></Svelecte>

Example for custom element:
Svelecte.config.i18n = {
  /** here replace all keys.*/
}
// local override
document.querySelector('el-svelecte').svelecte.$set({
  i18n: {
    // props to be overridden
  }
})
NOTE: Local I18n override is not supported for custom-element. In that case you need to access svelecte property and use component API ($set method) to update it programmatically.