Author: | Choices-js |
---|---|
Views Total: | 136 views |
Official Page: | Go to website |
Last Update: | March 14, 2025 |
License: | MIT |
Preview:

Description:
Choices.js is a vanilla JavaScript plugin that converts the normal select or input into customizable select inputs with multi-select and autocomplete support.
Great for creating multi-select tagging systems.
How to use it:
1. Install & download.
# Yarn $ yarn add choices.js # NPM $ npm i choices.js
2. Load the following JavaScript and Stylesheet in your document.
<link rel="stylesheet" href="/public/assets/styles/choices.min.css" /> <script src="/public/assets/scripts/choices.min.js"></script>
3. Create a simple tag input from a normal text field that
<input id="demo-1" type="text" value="tag-1,tag-2" placeholder="Enter something">
var firstElement = document.getElementById('demo-1'); var choices1 = new Choices(firstElement, { delimiter: ',', editItems: true, maxItems: 5, removeButton: true });
4. Create a multiple select input.
<select name="demo-2" id="demo-2" placeholder="This is a placeholder" multiple> <option value="Dropdown item 1">Dropdown item 1</option> <option value="Dropdown item 2">Dropdown item 2</option> <option value="Dropdown item 3" selected>Dropdown item 3</option> <option value="Dropdown item 4" disabled>Dropdown item 4</option> </select>
var secondElement = new Choices('#demo-2', { allowSearch: false }).setValue(['Set value 1', 'Set value 2']);
5. Create a multiple select input that loads remote data via AJAX.
<select name="demo-3" id="demo-3" data-choice placeholder="Pick an Arctic Monkeys record"></select>
var choicesAjax = new Choices('#demo-2').ajax((callback) => { fetch('https://api.discogs.com/artists/391170/releases?token=QBRmstCkwXEvCjTclCpumbtNwvVkEzGAdELXyRyW') .then((response) => { response.json().then(function(data) { callback(data.releases, 'title', 'title'); }); }) .catch((error) => { callback(); }); })
6. All possible options and callbacks with default values.
// pre-selected items // an array of strings // or an array of objects items: [], /* add choices to select input [{ 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' }, }] */ choices: [], // suppress console errors and warnings silent: false, // the amount of choices to be rendered within the dropdown list renderChoiceLimit: -1, // the amount of items a user can input/select maxItemCount: -1, // Control how the dropdown closes after making a selection for select-one or select-multiple. // Boolean | 'auto' closeDropdownOnSelect: 'auto', // Make select-multiple with a max item count of 1 work similar to select-one does. // Selecting an item will auto-close the dropdown and swap any existing item for the just selected choice. // If applied to a select-one, it functions as above and not the standard select-one. singleModeForMultiSelect: false, // Whether a user can add choices dynamically. addChoices: false, // allows users to add new items addItems: true, // 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 addItemFilter: null, // allows users to remove items removeItems: true, // shows remove button removeItemButton: false, // Align item remove button left vs right removeItemButtonAlignLeft: false, // allows users to edit items editItems: false, // allows to render HTML allowHTML: true, // Whether HTML should be escaped on input when addItems or addChoices is true. // If false, user input will be treated as plain text. // If true, this can be used to perform XSS scripting attacks if you load choices from a remote source. allowHtmlUserInput: false, // allows to duplicate inputted/chosen items duplicateItemsAllowed: true, // custom delimiter delimiter: ',', // allows copy & paste paste: true, // enable live search searchEnabled: true, // whether choices should be filtered by input or not searchChoices: true, // the minimum length a search value should be before choices are searched searchFloor: 1, // the maximum amount of search results to show searchResultLimit: 4, // search fields searchFields: 'label', 'value', // or 'top', 'bottom' position: 'auto', // reset scroll position after new items have been added resetScrollPosition: true, // whether to sort choices and groups shouldSort: true, // whether to sort items shouldSortItems: false, /* sorter: function(a, b) { return b.label.length - a.label.length; }, */ sorter: utils_1.sortByAlpha, // You can pass along the shadowRoot from your application shadowRoot: null, // whether to show a placeholder placeholder: true, // placeholder value placeholderValue: null, // placeholder value for search field searchPlaceholderValue: null, // prepend a value to each item added/selected prependValue: null, // append a value to each item added/selected appendValue: null, // whether selected choices should be removed from the list // or 'always' renderSelectedChoices: 'auto', appendGroupInSearch: false, // custom messages loadingText: 'Loading...', noResultsText: 'No results found', noChoicesText: 'No choices to choose from', itemSelectText: 'Press to select', uniqueItemText: 'Only unique values can be added', customAddItemText: 'Only values matching specific conditions can be added', // functions addItemText: function (value) { return "Press Enter to add <b>\"".concat((0, utils_1.sanitise)(value), "\"</b>"); }, maxItemText: function (maxItemCount) { return "Only ".concat(maxItemCount, " values can be added"); }, removeItemIconText: () => `Remove item`, removeItemLabelText: (value) => `Remove item: ${value}`, valueComparer: function (value1, value2) { return value1 === value2; }, // fuse library options // https://fusejs.io/api/options.html fuseOptions: { includeScore: true }, // label ID to improve a11y labelId: '', // callbacks callbackOnInit: function(e){ // ... }, callbackOnCreateTemplates: : function(template){ // ... }, // default CSS class names 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', description: 'choices__description', 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', notice: 'choices__notice', addChoice: 'choices__item--selectable', 'add-choice', noResults: 'has-no-results', noChoices: 'has-no-choices', }
7. API methods.
const intance = new Choices(element, { // options here }); // init intance.init(); // destroy intance.destroy(); // refresh intance.refresh(withEvents: boolean = false, selectFirstOption: boolean = false); // enable/disable intance.enable(); intance.disable(); // highlight/unhighlight each chosen item intance.highlightAll(); intance.unhighlightAll(); // remove items intance.removeActiveItemsByValue(value); intance.removeActiveItems(excludedId); intance.removeHighlightedItems(runEvent?: boolean); // show/hide the dropdown intance.showDropdown(); intance.hideDropdown(); // set choices of select input via an array of objects (or function that returns array of object or promise of it), a value field name and a label field name. intance.setChoices(choicesArrayOrFetcher?: (InputChoice | InputGroup)[] | ((instance: Choices) => (InputChoice | InputGroup)[] | Promise<(InputChoice | InputGroup)[]>), value?: string | null, label?: string, replaceChoices?: boolean): this | Promise; // clear all choices intance.clearChoices(); // get value(s) intance.getValue(valueOnly) // set value(s) intance.setValue(items: string[] | InputChoice[]); // set choice(s) intance.setChoiceByValue(value: string | string[]); // remove all items, choices and groups intance.clearStore(); // clear input intance.clearInput();
8. Events.
element.addEventListener( 'change', function(event) { // each time an item is added & removed console.log(event.detail.value); }, false, ); element.addEventListener( 'addItem', function(event) { // each time an item is added console.log(event.detail.id); console.log(event.detail.value); console.log(event.detail.label); console.log(event.detail.customProperties); console.log(event.detail.groupValue); console.log(event.detail.keyCode); }, false, ); element.addEventListener( 'removeItem', function(event) { // each time an item is removed console.log(event.detail.id); console.log(event.detail.value); console.log(event.detail.label); console.log(event.detail.customProperties); console.log(event.detail.groupValue); }, false, ); element.addEventListener( 'highlightItem', function(event) { // each time an item is highlighted console.log(event.detail.id); console.log(event.detail.value); console.log(event.detail.label); console.log(event.detail.groupValue); }, false, ); element.addEventListener( 'unhighlightItem', function(event) { // each time an item is unhighlighted console.log(event.detail.id); console.log(event.detail.value); console.log(event.detail.label); console.log(event.detail.groupValue); }, false, ); element.addEventListener( 'choice', function(event) { // each time a choice is selected console.log(event.detail.choice); }, false, ); element.addEventListener( 'highlightChoice', function(event) { // fired when a choice from the dropdown is highlighted console.log(event.detail.el); }, false, ); element.addEventListener( 'search', function(event) { // fired when a user search choices console.log(event.detail.value); console.log(event.detail.resultCount); }, false, ); element.addEventListener( 'showDropdown', function(event) { // fired when the dropdown is shown }, false, ); element.addEventListener( 'hideDropdown', function(event) { // fired when the dropdown is hidden }, false, );
Changelog:
v11.1.0 (03/14/2025)
- Support <option> label attribute
- add KMP search algorithm (gated by build flag)
- Remove role=”textbox” from search input, per a11y practices.
v11.0.6 (02/27/2025)
- Bugfixes
- Changes to setChoices & clearChoices adjust how the selection and new choices combine when using replaceChoices: true is used to better match v10.2.0 and v11.0.3 behavior.
v11.0.5 (02/26/2025)
- Bugfixes
v11.0.4 (02/23/2025)
- Lots of bugs fixed
- Do not preventDefault on item to support dragging
v11.0.3 (12/28/2024)
- Lots of bugs fixed
v11.0.2 (09/08/2024)
- duplicateItemsAllowed option is now respected by setChoices() method
v11.0.2 (09/08/2024)
- duplicateItemsAllowed option is now respected by setChoices() method
- Pass getClassNames as the 3rd argument to callbackOnCreateTemplates callback
- Bug Fixes
v11.0.1 (08/29/2024)
- Fix form reset/clearStore method
v11.0.0 (08/27/2024)
- Improve performance of search/filtering with large number of choices.
- Improve performance of rendering a large number of items or choices and adding/removing items.
- Add closeDropdownOnSelect option, controls how the dropdown is close after selection is made.
- Allow choices.js to be imported on nodejs, useful for tests and also server side rendering. As windows.document is by default not defined, the default template rendering will not function. The callbackOnCreateTemplates callback must be used.
- config.classNames now accept arrays to support multiple classes.
- The original option list for the select is not destroyed, and all loaded choices are serialised to HTML for better compatibility with external javascript.
- New singleModeForMultiSelect feature to treat a select-single as if it was a select-multiple with a max item count of 1, and still auto-close the dropdown and swap the active item on selection.
- Remove item text can be localized.
- Allow user-created choices for selects. User input is escaped by default. At the risk of XSS attacks this can be disabled by allowHtmlUserInput.
- Render options without a group even if groups are present.
- Read data-labelclass/data-label-description from <option> HTML to drive adding a per-choice CSS label and description text when allowHtml: false.
- Add removeItemButtonAlignLeft option, to control if the remove item button is at the start or the end of the item.
- Add removeChoice method. Removes the choice from the choices.js object and any backing <option> HTML element
- Add refresh method. Reloads choices from the backing <select>s options.
- escapeForTemplate function is passed to the 2nd method of the callbackOnCreateTemplates callback.
- When allowHtml is false, default templates now render escaped html to innerHtml writing to innerText. This provides consistent rendering performance as innerText is quirky and slower than escaped html into innerHtml
- Shadow DOM support
- searchResultLimit can be set to -1 for no limit of search results to display.
- Bug Fixes
v10.2.0 (11/30/2022)
- Add JSON support to custom properties
- Allow overwrite of the $choices-z-index variable
- Bug Fixes
v10.1.0 (02/17/2022)
- Add option labelId to improve a11y
- Bug Fixes
v10.0.0 (01/03/2022)
- Upgrade to Fuse v6
- Introduce allowHTML option to allow people to disable injecting HTML into choices.
- Bug Fixes
v9.1.0 (12/20/2021)
- Bug Fixes
- Switch to dart-sass, fix npm audit issues
- Documentation of input type terms
- Solve deprecated warning using / for division outside of calc()
- Update release drafter to latest
- Convert to typescript
- Adds a variable for the z-index
v9.0.1 (11/18/2019)
- Bugfix
v9.0.0 (11/15/2019)
- Add missing type definitions + rename sortFn.
- Bugs fixed.
v8.0.0 (11/03/2019)
- The ability to pass multiple elements to one instance of Choices has been removed – now only one element can be associated with Choices
- The undocumented userDefaults static property has been removed
- The ajax method has been removed. setChoices can now be used to set choices dynamically
- The addItemFilterFn option has been renamed to addItemFilter and now supports regex’s
- Element.prototype.closest has been added to the required polyfill list
- The .is-hidden class has been replaced with the hidden attribute
- Bugs fixed
- Code refactoring
v7.1.5 (10/24/2019)
- Bugs fixed
v7.1.0 (10/22/2019)
- Bugs fixed
v7.0.3 (10/22/2019)
- Bugs fixed
02/23/2019
- v6.0.2: Resolve undefined error
02/19/2019
- v6.0.1
02/13/2019
- v6.0.0: callback to filter items before adding
02/12/2019
- v5.1.0: callback to filter items before adding
01/25/2019
- v4.1.4: Bugfix
11/26/2018
- v4.1.3: Fix set choice by value bug
11/25/2018
- v4.1.2: Fix form submission bug in firefox
11/03/2018
- v4.1.0: Disable input when loading remote data
10/31/2018
- v4.0.6: Disable at a later stage of intialising
If i needed to get data A REST call from my database, how do i implement it with your plugin ? http://localhost/ivr/new/Choices-master/rest_api.php/system_users
i created a REST call api for my Dbase, what parameters could be used for ur API?
http://localhost/ivr/new/Choices-master/rest_api.php/system_users
var choicesAjax = new Choices(‘#demo-2’).ajax((callback) => {
fetch(‘https://api.discogs.com/artists/391170/releases?token=QBRmstCkwXEvCjTclCpumbtNwvVkEzGAdELXyRyW’)
.then((response) => {
response.json().then(function(data) {
callback(data.releases, ‘title’, ‘title’);
});
})
.catch((error) => {
callback();
});
})
I could create a simple tag input from a normal text field but the end user can not edit the tags created. Is that possible please ? Thanks.
why i get this error : TypeError: (new Choices(…)).ajax is not a function ??
Because you tried to use with jQuery
i need a multi select with remove buttons how to i do that?
add one item
.setValue([‘Set value 1’]);
how remove these item with a function?
No a button or the spacebar
Hello, i try
element = new coices…
element.setValue….
element.clearChoices()
But it not works…
watch out for the example!!!!! this doesn’t work anymore:
maxItems: 5,
removeButton: true
I changed that for this:
maxItemCount: -1,
removeItemButton: false,
hi, i am unable to put > symbol as it encodes to &rt; can you please suggest where to update this ? to show just > symbols