Choices.js provides extensive configuration options to customize behavior, appearance, and functionality. All options are optional and will fall back to sensible defaults if not provided.
Fundamental settings that control basic plugin behavior and interaction patterns.
interface Options {
/**
* Suppress console errors and warnings
* @default false
*/
silent: boolean;
/**
* Pre-selected items for text inputs or default selections for selects
* @default []
*/
items: string[] | InputChoice[];
/**
* Available choices for select elements
* @default []
*/
choices: InputChoice[];
/**
* Maximum number of items that can be selected (-1 for unlimited)
* @default -1
*/
maxItemCount: number;
/**
* Whether to close dropdown after selection - 'auto' adapts based on element type
* @default 'auto'
*/
closeDropdownOnSelect: boolean | 'auto';
/**
* Treat multi-select as single-select for UI purposes
* @default false
*/
singleModeForMultiSelect: boolean;
}Usage Examples:
const choices = new Choices('#my-select', {
silent: true, // Suppress console warnings
maxItemCount: 5, // Limit to 5 selections
closeDropdownOnSelect: false, // Keep dropdown open after selection
items: ['Pre-selected item 1', 'Pre-selected item 2'],
choices: [
{ value: 'option1', label: 'Option One', selected: true },
{ value: 'option2', label: 'Option Two' },
]
});
// Dynamic choices loading
const choicesWithAsync = new Choices('#async-select', {
choices: async () => {
const response = await fetch('/api/choices');
return response.json();
}
});Options controlling how items and choices can be added, removed, and modified.
interface Options {
/**
* Allow adding custom choices to select elements
* @default false
*/
addChoices: boolean;
/**
* Allow adding custom items to text inputs
* @default true
*/
addItems: boolean;
/**
* Filter function or regex to validate new items
* @default (value) => !!value && value !== ''
*/
addItemFilter: string | RegExp | ((value: string) => boolean);
/**
* Allow removing items/selections
* @default true
*/
removeItems: boolean;
/**
* Show remove button on selected items
* @default false
*/
removeItemButton: boolean;
/**
* Position remove button on the left side
* @default false
*/
removeItemButtonAlignLeft: boolean;
/**
* Allow editing existing items in text inputs
* @default false
*/
editItems: boolean;
/**
* Allow duplicate items in text inputs
* @default true
*/
duplicateItemsAllowed: boolean;
}Usage Examples:
const choices = new Choices('#text-input', {
addItems: true,
removeItems: true,
removeItemButton: true,
editItems: true,
duplicateItemsAllowed: false,
addItemFilter: (value) => value.length >= 3, // Minimum 3 characters
});
// Using regex filter
const emailChoices = new Choices('#email-input', {
addItemFilter: /^[^\s@]+@[^\s@]+\.[^\s@]+$/ // Basic email validation
});Configuration for search functionality and filtering behavior.
interface Options {
/**
* Enable search functionality
* @default true
*/
searchEnabled: boolean;
/**
* Search through available choices (not just selected items)
* @default true
*/
searchChoices: boolean;
/**
* Minimum characters required to trigger search
* @default 1
*/
searchFloor: number;
/**
* Maximum number of search results to display (-1 for unlimited)
* @default 4
*/
searchResultLimit: number;
/**
* Object keys to search within when using object-based choices
* @default ['label', 'value']
*/
searchFields: string[];
/**
* Fuse.js options for fuzzy search functionality
* @default { includeScore: true }
*/
fuseOptions: IFuseOptions<unknown>;
}Usage Examples:
const choices = new Choices('#searchable-select', {
searchEnabled: true,
searchChoices: true,
searchFloor: 2, // Start searching after 2 characters
searchResultLimit: 10,
searchFields: ['label', 'value', 'customProperty'],
fuseOptions: {
threshold: 0.4, // More strict matching
keys: ['label', 'value']
}
});Options controlling visual appearance and UI behavior.
interface Options {
/**
* Show placeholder text in inputs
* @default true
*/
placeholder: boolean;
/**
* Custom placeholder text value
* @default null
*/
placeholderValue: string | null;
/**
* Placeholder text for search input
* @default null
*/
searchPlaceholderValue: string | null;
/**
* Text/value to prepend to all values
* @default null
*/
prependValue: string | null;
/**
* Text/value to append to all values
* @default null
*/
appendValue: string | null;
/**
* Whether to render selected choices in dropdown - true, false, or 'always'
* @default 'auto'
*/
renderSelectedChoices: boolean | 'always';
/**
* Maximum number of choices to render in dropdown (-1 for unlimited)
* @default -1
*/
renderChoiceLimit: number;
/**
* Dropdown position relative to input
* @default 'auto'
*/
position: PositionOptionsType;
/**
* Reset dropdown scroll position when opening
* @default true
*/
resetScrollPosition: boolean;
}Configuration for how choices and items are sorted and ordered.
interface Options {
/**
* Sort choices alphabetically
* @default true
*/
shouldSort: boolean;
/**
* Sort selected items
* @default false
*/
shouldSortItems: boolean;
/**
* Custom sorting function for choices
* @default sortByAlpha
*/
sorter: (a: ChoiceFull, b: ChoiceFull) => number;
}Customizable text strings and label functions for internationalization and customization.
interface Options {
/**
* Loading text displayed during async operations
* @default 'Loading...'
*/
loadingText: string;
/**
* Text shown when no search results found
* @default 'No results found'
*/
noResultsText: string;
/**
* Text shown when no choices available
* @default 'No choices to choose from'
*/
noChoicesText: string;
/**
* Text for item selection accessibility
* @default 'Press to select'
*/
itemSelectText: string;
/**
* Text shown when trying to add duplicate items
* @default 'Only unique values can be added'
*/
uniqueItemText: string;
/**
* Custom text when adding new items
* @default 'Only values matching specific conditions can be added'
*/
customAddItemText: string;
/**
* Function to generate text for add item action
* @default (value) => `Press Enter to add <b>"${value}"</b>`
*/
addItemText: (value: string) => string;
/**
* Function to generate text when max items reached
* @default (maxItemCount) => `Only ${maxItemCount} values can be added`
*/
maxItemText: (maxItemCount: number) => string;
/**
* Function to generate accessible text for remove item buttons
* @default () => 'Remove item'
*/
removeItemIconText: () => string;
/**
* Function to generate accessible label text for remove item buttons
* @default (value) => `Remove item: ${value}`
*/
removeItemLabelText: (value: string) => string;
}Advanced configuration for specialized use cases and integrations.
interface Options {
/**
* Allow HTML content in choices and items
* @default true
*/
allowHTML: boolean;
/**
* Allow HTML in user-provided input
* @default false
*/
allowHtmlUserInput: boolean;
/**
* Character used to separate multiple values
* @default ','
*/
delimiter: string;
/**
* Enable paste functionality for text inputs
* @default true
*/
paste: boolean;
/**
* Custom function to compare values for equality
* @default (choice1, choice2) => choice1 === choice2
*/
valueComparer: (choice1: string, choice2: string) => boolean;
/**
* ID of the label element for accessibility
* @default ''
*/
labelId: string;
/**
* Custom CSS class names for styling
*/
classNames: ClassNames;
/**
* Shadow DOM root for rendering (advanced)
* @default null
*/
shadowRoot: ShadowRoot | null;
/**
* Include group names in search results
* @default false
*/
appendGroupInSearch: boolean;
}Event handlers and callback functions for integration with external systems.
interface Options {
/**
* Callback function called after initialization
* @default null
*/
callbackOnInit: (() => void) | null;
/**
* Callback to customize template generation
* @default null
*/
callbackOnCreateTemplates: CallbackOnCreateTemplatesFn | null;
}Usage Examples:
const choices = new Choices('#my-select', {
callbackOnInit: () => {
console.log('Choices has been initialized');
},
callbackOnCreateTemplates: (template) => {
return {
item: (classNames, data) => {
return template(`
<div class="${classNames.item} custom-item">
<span>${data.label}</span>
<button type="button">Custom Action</button>
</div>
`);
}
};
}
});The complete default configuration object that can be referenced or modified:
const DEFAULT_CONFIG: Options = {
items: [],
choices: [],
silent: false,
renderChoiceLimit: -1,
maxItemCount: -1,
closeDropdownOnSelect: 'auto',
singleModeForMultiSelect: false,
addChoices: false,
addItems: true,
addItemFilter: (value) => !!value && value !== '',
removeItems: true,
removeItemButton: false,
removeItemButtonAlignLeft: false,
editItems: false,
allowHTML: false,
allowHtmlUserInput: 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,
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',
uniqueItemText: 'Only unique values can be added',
customAddItemText: 'Only values matching specific conditions can be added',
addItemText: (value) => `Press Enter to add <b>"${value}"</b>`,
maxItemText: (maxItemCount) => `Only ${maxItemCount} values can be added`,
removeItemIconText: () => 'Remove item',
removeItemLabelText: (value) => `Remove item: ${value}`,
valueComparer: (choice1, choice2) => choice1 === choice2,
labelId: '',
callbackOnInit: null,
callbackOnCreateTemplates: null,
classNames: DEFAULT_CLASSNAMES,
fuseOptions: {
includeScore: true,
isCaseSensitive: false,
shouldSort: true,
includeMatches: true,
findAllMatches: false,
minMatchCharLength: 1,
location: 0,
threshold: 0.6,
distance: 100,
},
shadowRoot: null,
appendGroupInSearch: false,
};