Валидация вводимых значений

Проверка корректности вводимых данных в Choices.js строится вокруг комбинации встроенных ограничений компонента, конфигурационных параметров и перехвата пользовательских действий через события экземпляра. Библиотека не навязывает единую систему валидации, а предоставляет набор точек расширения, через которые реализуется контроль значений на уровне интерфейса и данных.

Choices.js оперирует сущностями «choice» и «item».

  • Choice — доступный вариант из списка.
  • Item — выбранное или введённое значение.

При включённом режиме пользовательского ввода (addItems: true) допускается создание новых элементов, которые не присутствуют в исходном списке. Именно этот режим требует основного внимания при реализации валидации.

Процесс добавления нового значения проходит через внутренний пайплайн:

  1. получение строки ввода;
  2. предварительная обработка (trim, нормализация);
  3. проверка на дубликаты (если включено);
  4. добавление элемента в коллекцию;
  5. триггер событий addItem.

На каждом этапе возможно вмешательство через конфигурацию или внешнюю логику.

Ограничение дубликатов как базовый механизм контроля

Одним из ключевых встроенных механизмов является запрет повторов:

const choices = new Choices(element, {
  duplicateItems: false
});

При значении false повторное добавление одинаковых значений блокируется. Сравнение выполняется по значению строки или ключу объекта, если используется объектный формат данных.

Поведение при попытке добавления дубликата зависит от версии и конфигурации: элемент либо игнорируется, либо не проходит стадию добавления.

Ограничение количества значений

Контроль объёма выбранных данных реализуется через параметр:

const choices = new Choices(element, {
  maxItemCount: 5,
  maxItemText: 'Достигнут лимит'
});

maxItemCount ограничивает число выбранных элементов, а maxItemText определяет текст, отображаемый при попытке превышения лимита.

Данный механизм является формой валидации на уровне структуры данных, предотвращающей перегрузку списка выбранных значений.

Перехват добавления элементов через события

Основной инструмент гибкой валидации — событие добавления элемента:

element.addEventListener('addItem', (event) => {
  const { value } = event.detail;
});

Событие addItem содержит объект detail, включающий добавляемое значение. На этом этапе возможно применение любых правил:

  • проверка длины строки;
  • соответствие регулярному выражению;
  • проверка диапазона чисел;
  • фильтрация по словарю запрещённых значений.

При необходимости добавленный элемент может быть удалён сразу после создания:

choices.removeActiveItemsByValue(value);

Такой подход формирует пост-валидацию, когда элемент сначала добавляется, а затем отклоняется при несоответствии условиям.

Предварительная валидация через фильтрацию ввода

Наиболее строгий контроль реализуется до добавления элемента. Для этого используется внешний обработчик, перехватывающий ввод пользователя до передачи в Choices.js.

Пример логики:

const isValid = (value) => {
  return /^[a-zA-Z0-9_-]{3,20}$/.test(value);
};

Далее добавление выполняется только при успешной проверке:

if (isValid(inputValue)) {
  choices.setValue([{ value: inputValue, label: inputValue }]);
}

Такой подход полностью исключает попадание некорректных данных в внутреннее состояние компонента.

Контроль допустимых значений через список choices

Если режим пользовательского ввода отключён, валидация сводится к выбору из фиксированного набора:

const choices = new Choices(element, {
  addItems: false
});

В этом режиме ввод ограничивается поиском по существующим вариантам. Любое значение, отсутствующее в списке, не может быть добавлено.

Фактически используется стратегия whitelist, где допустимые значения задаются заранее.

Ограничение поиска как косвенная валидация

Поисковый механизм также влияет на допустимость значений:

const choices = new Choices(element, {
  searchEnabled: true,
  searchFloor: 2
});

searchFloor задаёт минимальное количество символов для активации поиска. Это снижает вероятность ввода случайных или слишком коротких значений.

Дополнительно используется fuseOptions (если задействован Fuse.js внутри), что позволяет регулировать строгость нечеткого поиска и, косвенно, качество допустимых совпадений.

Очистка и нормализация значений

Валидация часто включает нормализацию перед сохранением:

  • удаление лишних пробелов;
  • приведение к нижнему регистру;
  • удаление спецсимволов.

Choices.js не выполняет глубокую нормализацию автоматически, поэтому используется внешний слой:

const normalize = (value) =>
  value.trim().toLowerCase();

После нормализации значение передаётся в компонент:

choices.setChoiceByValue(normalize(inputValue));

Проверка формата через пользовательскую логику

Для сложных сценариев применяется многоуровневая проверка:

  • синтаксическая (регулярные выражения);
  • семантическая (проверка по справочникам);
  • контекстная (зависимость от других выбранных значений).

Пример комбинированной проверки:

function validate(value, currentItems) {
  const formatOk = /^[0-9]{4}-[A-Z]{2}$/.test(value);
  const notDuplicate = !currentItems.includes(value);
  const businessRule = value.startsWith('202');

  return formatOk && notDuplicate && businessRule;
}

Такой подход позволяет реализовать доменно-ориентированную валидацию поверх UI-компонента.

Управление ошибочными вводами

Choices.js не содержит встроенной системы отображения ошибок, поэтому обработка строится вручную:

  • блокировка добавления;
  • подсветка input через CSS;
  • вывод сообщений вне компонента.

Пример реакции на ошибку:

element.classList.add('input-error');

или

showError('Недопустимое значение');

Удаление некорректных значений после вставки

В сценариях, где валидация происходит постфактум, применяется удаление:

choices.removeItemByValue(value);

Логика строится вокруг проверки состояния после события addItem.

Согласование валидации с состоянием компонента

При сложной логике важно учитывать внутреннее состояние Choices.js:

  • getValue(true) — получение текущих значений;
  • clearStore() — сброс состояния;
  • setValue() — принудительная синхронизация.

Пример проверки консистентности:

const values = choices.getValue(true);

values.forEach(v => {
  if (!validate(v.value, values)) {
    choices.removeActiveItemsByValue(v.value);
  }
});

Такой механизм используется для периодической очистки состояния.

Итоговая структура уровней валидации

Валидация вводимых значений в Choices.js обычно выстраивается в несколько слоёв:

  • ограничения конфигурации (duplicateItems, maxItemCount, addItems);
  • контроль выбора из списка (whitelist-режим);
  • перехват событий (addItem);
  • внешняя предварительная проверка;
  • пост-валидация через удаление элементов;
  • нормализация входных данных перед сохранением.

Такое разделение позволяет реализовать как простые формы выбора, так и сложные системы ввода с бизнес-правилами и строгими ограничениями.