Разделители для множественного ввода

В интерфейсах с множественным выбором библиотека Choices.js поддерживает сценарий, при котором пользователь вводит несколько значений в одно поле ввода, а затем они автоматически преобразуются в отдельные элементы. Основой этого поведения выступает механизм разделителей (delimiters), позволяющий разбивать строку ввода на отдельные элементы при определённых символах или действиях клавиатуры.

Разделитель определяет момент, в который введённый текст фиксируется как отдельный элемент списка и добавляется в состояние компонента.

Настройка параметра delimiter

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

const choices = new Choices('#tags', {
  delimiter: ','
});

Значение delimiter может быть любым символом или строкой. Наиболее распространённые варианты:

  • , — запятая
  • (пробел) — разделение по пробелу
  • ; — точка с запятой

При вводе текста библиотека отслеживает появление указанного символа и инициирует разбиение строки на отдельные элементы.

Поведение при вводе значений

При активированном разделителе ввод пользователя обрабатывается в режиме реального времени. Как только встречается символ delimiter, текущий фрагмент строки завершается и преобразуется в отдельный элемент списка.

Основные этапы обработки:

  1. Пользователь вводит строку в поле.
  2. Обнаруживается символ разделителя.
  3. Текущий ввод обрезается до символа.
  4. Значение добавляется как новый элемент.
  5. Поле ввода очищается для следующего значения.

При этом ввод не требует дополнительных действий вроде потери фокуса или нажатия кнопки подтверждения.

Использование клавиш как разделителей

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

const choices = new Choices('#tags', {
  addItemKeys: [13, 188]
});

Типичные коды клавиш:

  • 13 — Enter
  • 188 — запятая
  • 9 — Tab

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

Вставка из буфера обмена

Механизм разделителей также применяется при вставке текста из буфера обмена. Если вставляемая строка содержит символы, совпадающие с delimiter, библиотека автоматически разбивает строку на несколько элементов.

Пример поведения:

Вставка строки:

php, javascript, typescript, go

При delimiter: ',' результатом станет:

  • php
  • javascript
  • typescript
  • go

Каждое значение проходит через стандартный цикл обработки, включая фильтрацию и проверку на дубликаты.

Обработка пробелов и форматирование значений

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

Часто применяется внешняя очистка:

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

Пример логики обработки:

value.split(',').map(v => v.trim()).filter(Boolean);

Дубликаты и уникальность значений

Разделители напрямую взаимодействуют с системой предотвращения дублирования. При добавлении нового элемента через delimiter библиотека проверяет, существует ли уже такое значение в списке.

Контроль осуществляется через параметр:

const choices = new Choices('#tags', {
  duplicateItemsAllowed: false
});

Поведение при совпадении:

  • если дубликаты запрещены — значение игнорируется
  • если разрешены — создаётся отдельный элемент

При множественном вводе через разделители это особенно важно, так как вероятность повторного ввода значительно возрастает.

Валидация при множественном вводе

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

Типовые сценарии:

  • запрет пустых строк
  • проверка длины значения
  • ограничение по регулярному выражению

Пример проверки:

if (value.length < 2) {
  return;
}

Совместимость с режимом multiple

Механизм разделителей наиболее эффективно работает в режиме multiple, когда поле предназначено для хранения набора значений.

const choices = new Choices('#tags', {
  removeItemButton: true,
  duplicateItemsAllowed: false,
  delimiter: ','
});

В этом режиме каждое значение становится отдельным объектом внутри внутреннего массива value, а UI отображает их в виде отдельных тегов.

Поведение при редактировании значений

При включённой опции editItems пользователь может редактировать уже добавленные элементы. Однако разделители продолжают работать только в поле ввода, а не внутри уже созданных элементов.

const choices = new Choices('#tags', {
  editItems: true,
  delimiter: ','
});

Редактирование позволяет изменять значение элемента, но не инициирует автоматическое разделение внутри существующего тега.

Комбинирование с кастомными правилами добавления

Разделители часто используются вместе с фильтрацией через shouldSort, searchEnabled и пользовательские функции добавления.

Возможные комбинации:

  • отключение поиска при быстром вводе тегов
  • сортировка добавленных значений
  • динамическая фильтрация перед добавлением

Пример конфигурации:

const choices = new Choices('#tags', {
  delimiter: ',',
  searchEnabled: false,
  shouldSort: false,
  duplicateItemsAllowed: false,
  removeItemButton: true
});

Особенности обработки событий

При использовании разделителей активно генерируются события:

  • addItem
  • removeItem
  • change

Каждое добавление через delimiter эквивалентно программному вызову добавления элемента, что позволяет интегрировать дополнительную логику:

  • синхронизация с сервером
  • обновление состояния формы
  • валидация внешних систем

Событие addItem получает объект с добавленным значением, что позволяет отслеживать происхождение данных даже при массовом вводе через вставку текста.

Поведение при некорректных данных

Если строка содержит последовательные разделители, например:

php,,javascript,,,go

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

Типичная защита:

if (!value || !value.trim()) {
  return;
}