Customizable Select Box & Input Field Enhancement Library – Choices.js

Category: Form , Javascript , Recommended | January 3, 2022
Author:Choices-js
Views Total:572 views
Official Page:Go to website
Last Update:January 3, 2022
License:MIT

Preview:

Customizable Select Box & Input Field Enhancement Library – Choices.js

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,

// 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,

// allows users to edit items
editItems: false,

// allows to render HTML
allowHTML: true,

// 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,

// 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',

// 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");
},
valueComparer: function (value1, value2) {
  return value1 === value2;
},

// fuse library options
// https://fusejs.io/api/options.html
fuseOptions: {
  includeScore: true
},

// 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',
  itemOption: 'choices__item--choice',
  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',
  selectedState: 'is-highlighted',
}

7. API methods.

const intance = new Choices(element, {
  // options here
});

// init
intance.init();

// destroy
intance.destroy();

// 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();

// 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(choices, value, label, replaceChoices);

// clear all choices
intance.clearChoices();

// get value(s)
intance.getValue(valueOnly)

// set value(s)
intance.setValue(items);

// set choice(s)
intance.setChoiceByValue(value);

// 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:

v10.0.0 (01/03/2021)

  • 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

You Might Be Interested In:


10 thoughts on “Customizable Select Box & Input Field Enhancement Library – Choices.js

  1. Victor

    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();
    });
    })

    Reply
  2. Youne

    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.

    Reply
  3. adar

    why i get this error : TypeError: (new Choices(…)).ajax is not a function ??

    Reply
  4. JuanPa

    add one item
    .setValue([‘Set value 1’]);

    how remove these item with a function?
    No a button or the spacebar

    Reply
    1. Chritian

      Hello, i try

      element = new coices…
      element.setValue….
      element.clearChoices()

      But it not works…

      Reply
  5. Nelson

    watch out for the example!!!!! this doesn’t work anymore:
    maxItems: 5,
    removeButton: true

    I changed that for this:
    maxItemCount: -1,
    removeItemButton: false,

    Reply
  6. Ore

    hi, i am unable to put > symbol as it encodes to &rt; can you please suggest where to update this ? to show just > symbols

    Reply

Leave a Reply