or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configuration.mdcore-usage.mddata-management.mdevents.mdindex.mdtemplates.mdtypes.md
tile.json

configuration.mddocs/

Configuration

Complete reference for all 45+ configuration options that control Choices.js behavior, appearance, and functionality.

Options Interface

{ .api }
interface Options {
  // Core behavioral options
  silent: boolean;
  items: (string | Item)[];
  choices: (Choice | Group)[];
  renderSelectedChoices: 'always' | 'auto';
  maxItemCount: number;
  addItems: boolean;
  addItemFilter: string | RegExp | FilterFunction | null;
  removeItems: boolean;
  removeItemButton: boolean;
  editItems: boolean;
  allowHTML: boolean;
  duplicateItemsAllowed: boolean;
  delimiter: string;
  paste: boolean;
  searchEnabled: boolean;
  searchChoices: boolean;
  searchFloor: number;
  searchResultLimit: number;
  searchFields: string[] | string;
  position: PositionOptionsType;
  resetScrollPosition: boolean;
  shouldSort: boolean;
  shouldSortItems: boolean;
  sorter: (a: Choice | Item, b: Choice | Item) => number;
  placeholder: boolean;
  placeholderValue: string | null;
  searchPlaceholderValue: string | null;
  prependValue: string | null;
  appendValue: string | null;
  renderChoiceLimit: number;
  loadingText: string;
  noResultsText: string | StringFunction;
  noChoicesText: string | StringFunction;
  itemSelectText: string;
  uniqueItemText: string | StringFunction;
  customAddItemText: string | StringFunction;
  addItemText: string | StringFunction;
  maxItemText: string | StringFunction;
  valueComparer: ValueCompareFunction;
  fuseOptions: object;
  labelId: string;
  callbackOnInit: Function | null;
  callbackOnCreateTemplates: Function | null;
  classNames: ClassNames;
}

Default Configuration

{ .api }
const DEFAULT_CONFIG: Options = {
  silent: false,
  items: [],
  choices: [],
  renderSelectedChoices: 'auto',
  maxItemCount: -1,
  addItems: true,
  addItemFilter: null,
  removeItems: true,
  removeItemButton: false,
  editItems: false,
  allowHTML: true,
  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: defaultSorter,
  placeholder: true,
  placeholderValue: null,
  searchPlaceholderValue: null,
  prependValue: null,
  appendValue: null,
  renderChoiceLimit: -1,
  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: string) => `Press Enter to add <b>"${value}"</b>`,
  maxItemText: (maxItemCount: number) => `Only ${maxItemCount} values can be added`,
  valueComparer: (value1: string, value2: string) => value1 === value2,
  fuseOptions: { includeScore: true },
  labelId: '',
  callbackOnInit: null,
  callbackOnCreateTemplates: null,
  classNames: DEFAULT_CLASSNAMES
};

Core Behavioral Options

Basic Control

{ .api }
/**
 * Silent mode - suppresses console warnings
 */
silent: boolean; // Default: false

/**
 * Allow adding new items
 */
addItems: boolean; // Default: true

/**
 * Allow removing selected items
 */
removeItems: boolean; // Default: true

/**
 * Show remove button on selected items
 */
removeItemButton: boolean; // Default: false

/**
 * Allow editing of selected items
 */
editItems: boolean; // Default: false

Usage:

const choices = new Choices('#select', {
  addItems: true,
  removeItems: true,
  removeItemButton: true, // Show × button on items
  editItems: false        // Prevent editing selected items
});

Item Management

{ .api }
/**
 * Maximum number of items that can be selected (-1 for unlimited)
 */
maxItemCount: number; // Default: -1

/**
 * Allow duplicate items to be selected
 */
duplicateItemsAllowed: boolean; // Default: true

/**
 * Filter function/regex for validating new items
 */
addItemFilter: string | RegExp | FilterFunction | null; // Default: null

/**
 * Delimiter for parsing pasted content
 */
delimiter: string; // Default: ','

Usage:

const restrictedChoices = new Choices('#text-input', {
  maxItemCount: 3,
  duplicateItemsAllowed: false,
  addItemFilter: /^[A-Za-z\s]+$/, // Only letters and spaces
  delimiter: ';' // Use semicolon for pasting
});

HTML and Content

{ .api }
/**
 * Allow HTML content in choices and items
 */
allowHTML: boolean; // Default: true

/**
 * Enable pasting content into text inputs
 */
paste: boolean; // Default: true

/**
 * Text to prepend to all values
 */
prependValue: string | null; // Default: null

/**
 * Text to append to all values
 */
appendValue: string | null; // Default: null

Usage:

const safeChoices = new Choices('#select', {
  allowHTML: false,        // Prevent XSS
  prependValue: 'prefix_', // All values get prefix
  appendValue: '_suffix'   // All values get suffix
});

Search Configuration

Search Behavior

{ .api }
/**
 * Enable search functionality
 */
searchEnabled: boolean; // Default: true

/**
 * Enable searching through choices
 */
searchChoices: boolean; // Default: true

/**
 * Minimum characters before search starts
 */
searchFloor: number; // Default: 1

/**
 * Maximum number of search results to show
 */
searchResultLimit: number; // Default: 4

/**
 * Fields to search in (for objects)
 */
searchFields: string[] | string; // Default: ['label', 'value']

Usage:

const searchableChoices = new Choices('#select', {
  searchEnabled: true,
  searchChoices: true,
  searchFloor: 2,        // Start search after 2 characters
  searchResultLimit: 10, // Show up to 10 results
  searchFields: ['label', 'value', 'customProperty']
});

Fuzzy Search (Fuse.js)

{ .api }
/**
 * Configuration for Fuse.js fuzzy search
 */
fuseOptions: object; // Default: { includeScore: true }

Usage:

const fuzzyChoices = new Choices('#select', {
  fuseOptions: {
    threshold: 0.3,    // Lower = more strict matching
    location: 0,       // Search from beginning
    distance: 100,     // Maximum search distance
    keys: ['label']    // Keys to search in
  }
});

Display Options

Placeholder Configuration

{ .api }
/**
 * Show placeholder text
 */
placeholder: boolean; // Default: true

/**
 * Placeholder text for main input
 */
placeholderValue: string | null; // Default: null

/**
 * Placeholder text for search input
 */
searchPlaceholderValue: string | null; // Default: null

Usage:

const placeholderChoices = new Choices('#select', {
  placeholder: true,
  placeholderValue: 'Choose an option...',
  searchPlaceholderValue: 'Type to search...'
});

Rendering Control

{ .api }
/**
 * When to render selected choices in dropdown
 */
renderSelectedChoices: 'always' | 'auto'; // Default: 'auto'

/**
 * Maximum choices to render in dropdown (-1 for all)
 */
renderChoiceLimit: number; // Default: -1

Usage:

const renderChoices = new Choices('#multi-select', {
  renderSelectedChoices: 'always', // Show selected in dropdown
  renderChoiceLimit: 50            // Limit for performance
});

Sorting Configuration

{ .api }
/**
 * Sort choices alphabetically
 */
shouldSort: boolean; // Default: true

/**
 * Sort selected items
 */
shouldSortItems: boolean; // Default: false

/**
 * Custom sorting function
 */
sorter: (a: Choice | Item, b: Choice | Item) => number;

Usage:

const sortedChoices = new Choices('#select', {
  shouldSort: true,
  shouldSortItems: true,
  sorter: (a, b) => {
    // Custom sort by label length
    return a.label.length - b.label.length;
  }
});

Position and Layout

{ .api }
/**
 * Dropdown position relative to input
 */
position: PositionOptionsType; // 'auto' | 'top' | 'bottom' - Default: 'auto'

/**
 * Reset scroll position when dropdown opens
 */
resetScrollPosition: boolean; // Default: true

Usage:

const positionedChoices = new Choices('#select', {
  position: 'top',           // Force dropdown above
  resetScrollPosition: false // Maintain scroll position
});

Text and Localization

User-Facing Text

{ .api }
/**
 * Loading indicator text
 */
loadingText: string; // Default: 'Loading...'

/**
 * No search results text
 */
noResultsText: string | StringFunction; // Default: 'No results found'

/**
 * No choices available text
 */
noChoicesText: string | StringFunction; // Default: 'No choices to choose from'

/**
 * Screen reader text for selection
 */
itemSelectText: string; // Default: 'Press to select'

Dynamic Text Functions

{ .api }
/**
 * Text for duplicate item attempts
 */
uniqueItemText: string | StringFunction;

/**
 * Text for custom add item validation
 */
customAddItemText: string | StringFunction;

/**
 * Text for adding new items
 */
addItemText: string | StringFunction;

/**
 * Text when maximum items reached
 */
maxItemText: string | StringFunction;

Usage:

const localizedChoices = new Choices('#select', {
  loadingText: 'Cargando...',
  noResultsText: 'Sin resultados',
  noChoicesText: 'No hay opciones',
  addItemText: (value) => `Presiona Enter para añadir "${value}"`,
  maxItemText: (max) => `Solo se pueden añadir ${max} elementos`
});

Initial Data

{ .api }
/**
 * Initial items (selected values)
 */
items: (string | Item)[];

/**
 * Initial choices (available options)
 */
choices: (Choice | Group)[];

Usage:

const preloadedChoices = new Choices('#select', {
  items: ['preselected1', 'preselected2'],
  choices: [
    { value: 'choice1', label: 'Choice 1' },
    { value: 'choice2', label: 'Choice 2', selected: true },
    { 
      label: 'Group 1',
      id: 1,
      disabled: false,
      choices: [
        { value: 'grouped1', label: 'Grouped Choice 1' }
      ]
    }
  ]
});

Advanced Options

Comparison Function

{ .api }
/**
 * Function to compare values for equality
 */
valueComparer: ValueCompareFunction;

Usage:

const customComparer = new Choices('#select', {
  valueComparer: (value1, value2) => {
    // Case-insensitive comparison
    return value1.toLowerCase() === value2.toLowerCase();
  }
});

Accessibility

{ .api }
/**
 * ID for labeling the input (accessibility)
 */
labelId: string; // Default: ''

Usage:

// HTML
// <label id="my-label">Select Options</label>
// <select id="my-select"></select>

const accessibleChoices = new Choices('#my-select', {
  labelId: 'my-label'
});

Callbacks

{ .api }
/**
 * Callback function called after initialization
 */
callbackOnInit: Function | null;

/**
 * Callback for customizing templates
 */
callbackOnCreateTemplates: Function | null;

Usage:

const callbackChoices = new Choices('#select', {
  callbackOnInit: function() {
    console.log('Choices initialized!');
  },
  callbackOnCreateTemplates: function(template) {
    return {
      ...template,
      item: (item) => `<div class="custom-item">${item.label}</div>`
    };
  }
});

CSS Class Names

{ .api }
/**
 * Custom CSS class names for all components
 */
classNames: ClassNames;

Usage:

const styledChoices = new Choices('#select', {
  classNames: {
    containerOuter: 'custom-choices',
    containerInner: 'custom-choices__inner',
    input: 'custom-choices__input',
    item: 'custom-choices__item',
    // ... other class overrides
  }
});

Configuration Patterns

Text Input Configuration

const textConfig = {
  delimiter: ',',
  editItems: true,
  maxItemCount: -1,
  removeItemButton: true,
  duplicateItemsAllowed: false
};

Single Select Configuration

const singleConfig = {
  searchEnabled: true,
  itemSelectText: 'Click to select',
  shouldSort: true,
  placeholder: true,
  placeholderValue: 'Choose one option'
};

Multi-Select Configuration

const multiConfig = {
  removeItemButton: true,
  maxItemCount: 10,
  renderSelectedChoices: 'always',
  searchResultLimit: 8
};

Performance Configuration

const performanceConfig = {
  searchResultLimit: 20,
  renderChoiceLimit: 100,
  shouldSort: false,
  resetScrollPosition: false
};

This comprehensive configuration reference enables complete customization of Choices.js behavior for any use case.