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

data-management.mddocs/

Data Management

Comprehensive guide for managing choices, selected items, and values in Choices.js with full programmatic control over data operations.

Core Data Types

{ .api }
interface Choice {
  id: number;
  label: string;
  value: string;
  selected: boolean;
  disabled: boolean;
  customProperties?: Record<string, any>;
}

interface Item extends Choice {
  choiceId: number;
  highlighted: boolean;
}

interface Group {
  id: number;
  value: string;
  active: boolean;
  disabled: boolean;
  choices?: Choice[];
}

Choice Management

Set Available Choices

{ .api }
/**
 * Set the available choices for selection
 * @param choices - Array of choice objects or groups
 * @param value - Property name for value (default: 'value')
 * @param label - Property name for label (default: 'label') 
 * @param replaceChoices - Replace existing choices (default: false)
 * @returns {Choices} - Returns instance for chaining
 */
setChoices(
  choices: (Choice | Group)[], 
  value?: string, 
  label?: string, 
  replaceChoices?: boolean
): Choices

Basic Usage:

// Simple choices array
choices.setChoices([
  { value: 'option1', label: 'Option 1' },
  { value: 'option2', label: 'Option 2', selected: true },
  { value: 'option3', label: 'Option 3', disabled: true }
]);

// Replace all existing choices
choices.setChoices(newChoices, 'value', 'label', true);

Custom Property Mapping:

// Custom property names
const apiData = [
  { id: 1, name: 'First Choice', code: 'FIRST' },
  { id: 2, name: 'Second Choice', code: 'SECOND' }
];

choices.setChoices(apiData, 'code', 'name');
// Maps 'code' to value, 'name' to label

With Groups:

const groupedChoices = [
  {
    label: 'Fruits',
    id: 1,
    disabled: false,
    choices: [
      { value: 'apple', label: 'Apple' },
      { value: 'banana', label: 'Banana' }
    ]
  },
  {
    label: 'Vegetables', 
    id: 2,
    disabled: false,
    choices: [
      { value: 'carrot', label: 'Carrot' },
      { value: 'lettuce', label: 'Lettuce' }
    ]
  }
];

choices.setChoices(groupedChoices);

With Custom Properties:

const enrichedChoices = [
  {
    value: 'premium',
    label: 'Premium Plan',
    customProperties: {
      price: 29.99,
      features: ['Advanced Analytics', 'Priority Support'],
      badge: 'Most Popular'
    }
  },
  {
    value: 'basic',
    label: 'Basic Plan', 
    customProperties: {
      price: 9.99,
      features: ['Basic Analytics'],
      badge: null
    }
  }
];

choices.setChoices(enrichedChoices);

// Access custom properties in templates or events
choices.passedElement.element.addEventListener('addItem', (event) => {
  const customProps = event.detail.customProperties;
  console.log('Selected plan price:', customProps.price);
});

Clear All Choices

{ .api }
/**
 * Remove all available choices from dropdown
 * @returns {Choices} - Returns instance for chaining
 */
clearChoices(): Choices

Usage:

// Remove all choices but keep selected items
choices.clearChoices();

// Typically followed by new choices
choices.clearChoices().setChoices(newChoicesArray);

Dynamic Choice Loading

// Async loading pattern
async function loadChoices(searchTerm) {
  choices.clearChoices();
  
  const response = await fetch(`/api/choices?search=${searchTerm}`);
  const data = await response.json();
  
  choices.setChoices(data.results, 'id', 'name', true);
}

// Debounced search
let searchTimeout;
choices.input.element.addEventListener('input', (event) => {
  clearTimeout(searchTimeout);
  searchTimeout = setTimeout(() => {
    loadChoices(event.target.value);
  }, 300);
});

Value and Item Management

Set Selected Values

{ .api }
/**
 * Set the selected value(s) programmatically
 * @param items - Values to select (string, array, or item objects)
 * @returns {Choices} - Returns instance for chaining
 */
setValue(items: string[] | string | Item[] | Item): Choices

String Values:

// Single value
choices.setValue('option1');

// Multiple values
choices.setValue(['option1', 'option2', 'option3']);

// Empty array clears selection
choices.setValue([]);

Item Objects:

// Single item object
choices.setValue({
  value: 'custom',
  label: 'Custom Option',
  customProperties: { source: 'manual' }
});

// Multiple item objects
choices.setValue([
  { value: 'item1', label: 'Item 1' },
  { value: 'item2', label: 'Item 2' }
]);

Get Current Values

{ .api }
/**
 * Get current values or items
 * @param valueOnly - Return only values (true) or full items (false)
 * @returns {string | string[] | Item | Item[]} Current selection
 */
getValue(valueOnly?: boolean): string | string[] | Item | Item[]

Usage:

// Get values only (default)
const values = choices.getValue(); // ['value1', 'value2']
const values = choices.getValue(true); // ['value1', 'value2']

// Get full item objects
const items = choices.getValue(false);
// Returns: [
//   { id: 1, value: 'value1', label: 'Label 1', selected: true, choiceId: 10 },
//   { id: 2, value: 'value2', label: 'Label 2', selected: true, choiceId: 11 }
// ]

// For single select, returns single value/item (not array)
const singleValue = singleSelectChoices.getValue(); // 'selected-value'
const singleItem = singleSelectChoices.getValue(false); // { id: 1, value: '...', ... }

Select by Value

{ .api }
/**
 * Select an existing choice by its value
 * @param value - The value to select
 * @returns {Choices} - Returns instance for chaining
 */
setChoiceByValue(value: string): Choices

Usage:

// Select from existing choices
choices.setChoiceByValue('existing-option');

// Works with multi-select (adds to selection)
multiChoices.setChoiceByValue('additional-option');

// No effect if value doesn't exist in choices
choices.setChoiceByValue('nonexistent-value');

Item Removal Operations

Remove by Value

{ .api }
/**
 * Remove selected items by their values
 * @param value - Value to remove
 * @returns {Choices} - Returns instance for chaining
 */
removeActiveItemsByValue(value: string): Choices

Usage:

// Remove specific item
choices.removeActiveItemsByValue('unwanted-option');

// Remove multiple (call multiple times)
['item1', 'item2'].forEach(value => {
  choices.removeActiveItemsByValue(value);
});

Remove Active Items

{ .api }
/**
 * Remove active items, optionally excluding one
 * @param excludedId - ID of item to keep (optional)
 * @returns {Choices} - Returns instance for chaining
 */
removeActiveItems(excludedId?: number): Choices

Usage:

// Remove all selected items
choices.removeActiveItems();

// Remove all except specific item
const keepItem = choices.getValue(false)[0]; // Get first item
choices.removeActiveItems(keepItem.id);

Remove Highlighted Items

{ .api }
/**
 * Remove currently highlighted items
 * @param runEvent - Whether to trigger removeItem event
 * @returns {Choices} - Returns instance for chaining
 */
removeHighlightedItems(runEvent?: boolean): Choices

Usage:

// Remove highlighted items (typically from keyboard interaction)
choices.removeHighlightedItems();

// Remove without triggering events
choices.removeHighlightedItems(false);

Item Highlighting

Highlight Specific Item

{ .api }
/**
 * Highlight an item (visual selection state)
 * @param item - Item to highlight
 * @param runEvent - Whether to trigger highlightItem event
 * @returns {Choices} - Returns instance for chaining
 */
highlightItem(item: Item, runEvent?: boolean): Choices

Remove Item Highlight

{ .api }
/**
 * Remove highlight from an item
 * @param item - Item to unhighlight
 * @returns {Choices} - Returns instance for chaining
 */
unhighlightItem(item: Item): Choices

Bulk Highlighting

{ .api }
/**
 * Highlight all selected items
 * @returns {Choices} - Returns instance for chaining
 */
highlightAll(): Choices

/**
 * Remove highlights from all items
 * @returns {Choices} - Returns instance for chaining
 */
unhighlightAll(): Choices

Usage:

// Get items for highlighting
const items = choices.getValue(false);

// Highlight specific item
choices.highlightItem(items[0]);

// Bulk operations
choices.highlightAll();    // Highlight everything
choices.unhighlightAll();  // Clear all highlights

// Keyboard-style selection
choices.unhighlightAll();
choices.highlightItem(items[2]); // Highlight only third item

Data Synchronization Patterns

Form Integration

// Sync with hidden form input
const hiddenInput = document.getElementById('hidden-values');
choices.passedElement.element.addEventListener('change', (event) => {
  hiddenInput.value = JSON.stringify(event.detail.value);
});

// Initialize from hidden input
if (hiddenInput.value) {
  const savedValues = JSON.parse(hiddenInput.value);
  choices.setValue(savedValues);
}

State Management Integration

// Redux/Vuex pattern
function syncChoicesWithStore(choices, store) {
  // Update store when choices change
  choices.passedElement.element.addEventListener('change', (event) => {
    store.dispatch('updateSelection', event.detail.value);
  });
  
  // Update choices when store changes
  store.subscribe(() => {
    const currentSelection = store.getState().selection;
    choices.setValue(currentSelection);
  });
}

API Synchronization

// Auto-save changes
choices.passedElement.element.addEventListener('addItem', async (event) => {
  await fetch('/api/user/preferences', {
    method: 'POST',
    body: JSON.stringify({ 
      selectedItems: choices.getValue() 
    })
  });
});

// Load from API
async function initializeFromAPI(choices) {
  const [choicesData, selectedData] = await Promise.all([
    fetch('/api/choices').then(r => r.json()),
    fetch('/api/user/selected').then(r => r.json())
  ]);
  
  choices.setChoices(choicesData);
  choices.setValue(selectedData);
}

Bulk Operations

Efficient Bulk Updates

// Avoid multiple DOM updates
choices.clearStore(); // Clear everything at once

// Set everything in one operation
choices.setChoices(allChoices, 'value', 'label', true);
choices.setValue(selectedValues);

// Chain operations to minimize renders
choices
  .clearChoices()
  .setChoices(newChoices)
  .setValue(newSelection);

Data Transformation

// Transform API data to Choices format
function transformAPIData(apiResponse) {
  return apiResponse.items.map(item => ({
    value: item.id,
    label: item.displayName,
    disabled: !item.active,
    customProperties: {
      category: item.category,
      metadata: item.metadata
    }
  }));
}

// Apply transformation
const transformedData = transformAPIData(apiData);
choices.setChoices(transformedData, 'value', 'label', true);

Filtering and Searching

// Custom filtering
function filterChoicesByCategory(choices, category) {
  const filtered = choices.filter(choice => 
    choice.customProperties?.category === category
  );
  return filtered;
}

// Apply filter
const categoryChoices = filterChoicesByCategory(allChoices, 'premium');
choices.setChoices(categoryChoices, 'value', 'label', true);

// Search-based filtering
function searchChoices(choices, searchTerm) {
  return choices.filter(choice => 
    choice.label.toLowerCase().includes(searchTerm.toLowerCase()) ||
    choice.value.toLowerCase().includes(searchTerm.toLowerCase())
  );
}

Validation and Error Handling

// Validate before setting
function setValidatedChoices(choices, newChoices) {
  const valid = newChoices.every(choice => 
    choice.value && choice.label && 
    typeof choice.value === 'string'
  );
  
  if (!valid) {
    console.error('Invalid choice data');
    return;
  }
  
  choices.setChoices(newChoices);
}

// Handle missing values gracefully
function safeSetValue(choices, values) {
  const availableValues = choices.getValue().map(item => item.value);
  const validValues = values.filter(value => 
    availableValues.includes(value)
  );
  
  choices.setValue(validValues);
}

This comprehensive data management guide covers all operations for effectively controlling Choices.js data state and synchronization.