README
Choices.js
A vanilla, lightweight (~19kb gzipped 🎉), configurable select box/text input plugin. Similar to Select2 and Selectize but without the jQuery dependency.
TL;DR
- Lightweight
- No jQuery dependency
- Configurable sorting
- Flexible styling
- Fast search/filtering
- Clean API
- Right-to-left support
- Custom templates
ES6.io for great tutorials! 💪🏼
Interested in writing your own ES6 JavaScript plugins? Check outInstallation
With NPM:
npm install choices.js
With Yarn:
yarn add choices.js
From a CDN:
Note: There is sometimes a delay before the latest version of Choices is reflected on the CDN.
<!-- Include base CSS (optional) -->
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/choices.js/public/assets/styles/base.min.css"
/>
<!-- Include Choices CSS -->
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/choices.js/public/assets/styles/choices.min.css"
/>
<!-- Include Choices JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/choices.js/public/assets/scripts/choices.min.js"></script>
Or include Choices directly:
<!-- Include base CSS (optional) -->
<link rel="stylesheet" href="public/assets/styles/base.min.css" />
<!-- Include Choices CSS -->
<link rel="stylesheet" href="public/assets/styles/choices.min.css" />
<!-- Include Choices JavaScript -->
<script src="/public/assets/scripts/choices.min.js"></script>
Setup
Note: If you pass a selector which targets multiple elements, the first matching element will be used. Versions prior to 8.x.x would return multiple Choices instances.
// Pass single element
const element = document.querySelector('.js-choice');
const choices = new Choices(element);
// Pass reference
const choices = new Choices('[data-trigger]');
const choices = new Choices('.js-choice');
// Pass jQuery element
const choices = new Choices($('.js-choice')[0]);
// Passing options (with default options)
const choices = new Choices(element, {
silent: false,
items: [],
choices: [],
renderChoiceLimit: -1,
maxItemCount: -1,
addItems: true,
addItemFilter: null,
removeItems: true,
removeItemButton: false,
editItems: false,
duplicateItemsAllowed: true,
delimiter: ',',
paste: true,
searchEnabled: true,
searchChoices: true,
searchFloor: 1,
searchResultLimit: 4,
searchFields: ['label', 'value'],
position: 'auto',
resetScrollPosition: true,
shouldSort: true,
shouldSortItems: false,
sorter: () => {...},
placeholder: true,
placeholderValue: null,
searchPlaceholderValue: null,
prependValue: null,
appendValue: null,
renderSelectedChoices: 'auto',
loadingText: 'Loading...',
noResultsText: 'No results found',
noChoicesText: 'No choices to choose from',
itemSelectText: 'Press to select',
addItemText: (value) => {
return `Press Enter to add <b>"${value}"</b>`;
},
maxItemText: (maxItemCount) => {
return `Only ${maxItemCount} values can be added`;
},
valueComparer: (value1, value2) => {
return value1 === value2;
},
classNames: {
containerOuter: 'choices',
containerInner: 'choices__inner',
input: 'choices__input',
inputCloned: 'choices__input--cloned',
list: 'choices__list',
listItems: 'choices__list--multiple',
listSingle: 'choices__list--single',
listDropdown: 'choices__list--dropdown',
item: 'choices__item',
itemSelectable: 'choices__item--selectable',
itemDisabled: 'choices__item--disabled',
itemChoice: 'choices__item--choice',
placeholder: 'choices__placeholder',
group: 'choices__group',
groupHeading: 'choices__heading',
button: 'choices__button',
activeState: 'is-active',
focusState: 'is-focused',
openState: 'is-open',
disabledState: 'is-disabled',
highlightedState: 'is-highlighted',
selectedState: 'is-selected',
flippedState: 'is-flipped',
loadingState: 'is-loading',
noResults: 'has-no-results',
noChoices: 'has-no-choices'
},
// Choices uses the great Fuse library for searching. You
// can find more options here: https://github.com/krisk/Fuse#options
fuseOptions: {
include: 'score'
},
callbackOnInit: null,
callbackOnCreateTemplates: null
});
Terminology
Word | Definition |
---|---|
Choice | A choice is a value a user can select. A choice would be equivalent to the <option></option> element within a select input. |
Group | A group is a collection of choices. A group should be seen as equivalent to a <optgroup></optgroup> element within a select input. |
Item | An item is an inputted value (text input) or a selected choice (select element). In the context of a select element, an item is equivalent to a selected option element: <option value="Hello" selected></option> whereas in the context of a text input an item is equivalent to <input type="text" value="Hello"> |
Configuration options
silent
Type: Boolean
Default: false
Input types affected: text
, select-single
, select-multiple
Usage: Optionally suppress console errors and warnings.
items
Type: Array
Default: []
Input types affected: text
Usage: Add pre-selected items (see terminology) to text input.
Pass an array of strings:
['value 1', 'value 2', 'value 3']
Pass an array of objects:
[{
value: 'Value 1',
label: 'Label 1',
id: 1
},
{
value: 'Value 2',
label: 'Label 2',
id: 2,
customProperties: {
random: 'I am a custom property'
}
}]
choices
Type: Array
Default: []
Input types affected: select-one
, select-multiple
Usage: Add choices (see terminology) to select input.
Pass an array of objects:
[{
value: 'Option 1',
label: 'Option 1',
selected: true,
disabled: false,
},
{
value: 'Option 2',
label: 'Option 2',
selected: false,
disabled: true,
customProperties: {
description: 'Custom description about Option 2',
random: 'Another random custom property'
},
}]
renderChoiceLimit
Type: Number
Default: -1
Input types affected: select-one
, select-multiple
Usage: The amount of choices to be rendered within the dropdown list ("-1" indicates no limit). This is useful if you have a lot of choices where it is easier for a user to use the search area to find a choice.
maxItemCount
Type: Number
Default: -1
Input types affected: text
, select-multiple
Usage: The amount of items a user can input/select ("-1" indicates no limit).
addItems
Type: Boolean
Default: true
Input types affected: text
Usage: Whether a user can add items.
removeItems
Type: Boolean
Default: true
Input types affected: text
, select-multiple
Usage: Whether a user can remove items.
removeItemButton
Type: Boolean
Default: false
Input types affected: text
, select-one
, select-multiple
Usage: Whether each item should have a remove button.
editItems
Type: Boolean
Default: false
Input types affected: text
Usage: Whether a user can edit items. An item's value can be edited by pressing the backspace.
duplicateItemsAllowed
Type: Boolean
Default: true
Input types affected: text
, select-multiple
Usage: Whether duplicate inputted/chosen items are allowed
delimiter
Type: String
Default: ,
Input types affected: text
Usage: What divides each value. The default delimiter seperates each value with a comma: "Value 1, Value 2, Value 3"
.
paste
Type: Boolean
Default: true
Input types affected: text
, select-multiple
Usage: Whether a user can paste into the input.
searchEnabled
Type: Boolean
Default: true
Input types affected: select-one
Usage: Whether a search area should be shown. Note: Multiple select boxes will always show search areas.
searchChoices
Type: Boolean
Default: true
Input types affected: select-one
Usage: Whether choices should be filtered by input or not. If false
, the search event will still emit, but choices will not be filtered.
searchFields
Type: Array/String
Default: ['label', 'value']
Input types affected:select-one
, select-multiple
Usage: Specify which fields should be used when a user is searching. If you have added custom properties to your choices, you can add these values thus: ['label', 'value', 'customProperties.example']
.
searchFloor
Type: Number
Default: 1
Input types affected: select-one
, select-multiple
Usage: The minimum length a search value should be before choices are searched.
searchResultLimit: 4,
Type: Number
Default: 4
Input types affected: select-one
, select-multiple
Usage: The maximum amount of search results to show.
shadowRoot
Type: Document Element Default: null
Input types affected: select-one
, select-multiple
Usage: You can pass along the shadowRoot from your application like so.
var shadowRoot = document
.getElementById('wrapper')
.attachShadow({ mode: 'open' });
var choices = new Choices({
shadowRoot: shadowRoot,
});
position
Type: String
Default: auto
Input types affected: select-one
, select-multiple
Usage: Whether the dropdown should appear above (top
) or below (bottom
) the input. By default, if there is not enough space within the window the dropdown will appear above the input, otherwise below it.
resetScrollPosition
Type: Boolean
Default: true
Input types affected: select-multiple
Usage: Whether the scroll position should reset after adding an item.
addItemFilter
Type: string | RegExp | Function
Default: null
Input types affected: text
Usage: A RegExp or string (will be passed to RegExp constructor internally) or filter function that will need to return true
for a user to successfully add an item.
Example:
// Only adds items matching the text test
new Choices(element, {
addItemFilter: (value) => {
return ['orange', 'apple', 'banana'].includes(value);
};
});
// only items ending to `-red`
new Choices(element, {
addItemFilter: '-red