Интеграция с HTML-формами

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


Подключение библиотеки к проекту

Choices.js может быть подключена несколькими способами: через CDN или через пакетный менеджер.

Подключение через CDN:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/choices.js/public/assets/styles/choices.min.css">
<script src="https://cdn.jsdelivr.net/npm/choices.js/public/assets/scripts/choices.min.js"></script>

Подключение через npm:

npm install choices.js
import Choices from "choices.js";
import "choices.js/public/assets/styles/choices.min.css";

После подключения библиотека становится доступной как конструктор Choices.


Базовая интеграция с <select>

Стандартный HTML-элемент:

<form>
  <label for="country">Страна</label>
  <select id="country" name="country">
    <option value="kz">Казахстан</option>
    <option value="ru">Россия</option>
    <option value="us">США</option>
  </select>
</form>

Инициализация Choices.js:

const countrySelect = document.getElementById("country");

const choices = new Choices(countrySelect);

После инициализации стандартный <select> заменяется кастомизированным UI, но сохраняет связь с формой. При отправке формы выбранное значение передаётся как обычное поле.


Поддержка множественного выбора

HTML:

<select id="skills" name="skills" multiple>
  <option value="js">JavaScript</option>
  <option value="ts">TypeScript</option>
  <option value="py">Python</option>
</select>

Jav * aScript:

const skills = new Choices("#skills", {
  removeItemButton: true
});

Ключевое поведение:

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

Работа с <input> как теговым полем

Choices.js может превращать текстовое поле в систему тегов:

<input id="tags" name="tags" type="text">
const tagInput = new Choices("#tags", {
  delimiter: ",",
  editItems: true,
  removeItemButton: true,
  duplicateItemsAllowed: false
});

Поведение:

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

Передача данных в HTML-форму

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

Пример формы:

<form id="profile">
  <select id="language" name="language">
    <option value="en">English</option>
    <option value="ru">Русский</option>
  </select>

  <button type="submit">Отправить</button>
</form>

Обработчик:

document.getElementById("profile").addEventListener("submit", (e) => {
  e.preventDefault();

  const formData = new FormData(e.target);
  console.log(Object.fromEntries(formData.entries()));
});

Choices.js не требует дополнительной сериализации, так как обновляет оригинальный DOM-элемент.


Динамическое управление значениями формы

Choices предоставляет API для изменения состояния поля.

Добавление значения программно:

choices.setChoiceByValue("ru");

Добавление нового элемента:

choices.setValue([
  { value: "de", label: "Germany", selected: true }
]);

Очистка выбранных значений:

choices.removeActiveItems();

Интеграция с серверными данными

Частый сценарий — загрузка данных из API.

fetch("/api/countries")
  .then(res => res.json())
  .then(data => {
    const select = document.getElementById("country");

    const choices = new Choices(select);

    choices.setChoices(
      data.map(item => ({
        value: item.code,
        label: item.name,
        selected: false
      })),
      "value",
      "label",
      true
    );
  });

Работа с валидацией форм

Choices.js не заменяет нативную валидацию HTML, но влияет на поведение UI.

Пример обязательного поля:

<select id="city" name="city" required>
  <option value="">Выберите город</option>
  <option value="astana">Астана</option>
</select>

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

Дополнительная кастомная проверка:

document.querySelector("form").addEventListener("submit", (e) => {
  if (!choices.getValue(true)) {
    e.preventDefault();
    console.log("Поле не заполнено");
  }
});

Синхронизация с внешним состоянием

Choices.js поддерживает реакцию на изменения DOM и программное обновление состояния.

choices.passedElement.element.addEventListener(
  "change",
  (event) => {
    console.log(event.detail.value);
  }
);

Также доступна реакция на добавление и удаление элементов:

choices.passedElement.element.addEventListener(
  "addItem",
  (event) => {
    console.log("Добавлено:", event.detail.value);
  }
);

choices.passedElement.element.addEventListener(
  "removeItem",
  (event) => {
    console.log("Удалено:", event.detail.value);
  }
);

Использование с несколькими формами

Одну и ту же логику можно применять к множеству элементов формы.

document.querySelectorAll("select").forEach((el) => {
  new Choices(el, {
    searchEnabled: true
  });
});

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


Сброс формы и Choices.js

При сбросе формы важно учитывать синхронизацию состояния.

HTML:

<form id="filterForm">
  <select id="filter" name="filter">
    <option value="all">Все</option>
    <option value="active">Активные</option>
  </select>

  <button type="reset">Сброс</button>
</form>

Jav * aScript:

const filterChoices = new Choices("#filter");

document.getElementById("filterForm").addEventListener("reset", () => {
  setTimeout(() => {
    filterChoices.removeActiveItems();
  }, 0);
});

Работа с disabled состояниями

Choices.js корректно обрабатывает отключенные элементы:

choices.disable();

И восстановление:

choices.enable();

Также можно блокировать отдельные элементы списка:

choices.setChoices([
  { value: "vip", label: "VIP", disabled: true }
]);

Особенности поведения внутри HTML-форм

Choices.js сохраняет следующие принципы:

  • оригинальный input/select остаётся частью DOM
  • значение всегда синхронизировано с UI
  • отправка формы не требует дополнительной обработки
  • поддерживается нативная валидация
  • возможна работа с серверным рендерингом

Типовые сценарии использования в формах

  • фильтры каталогов с множественным выбором категорий
  • формы регистрации с выбором навыков и интересов
  • теги для блогов и CMS
  • автокомплит городов, стран, адресов
  • динамические формы с API-данными

Ограничения при работе с формами

Несмотря на гибкость, существуют особенности:

  • сложные кастомные шаблоны требуют дополнительной синхронизации состояния
  • при внешнем изменении DOM без API возможна рассинхронизация
  • большие списки требуют оптимизации поиска
  • не все UI-изменения отражаются в нативном select без обновления Choices-инстанса