Ограничение количества выбранных элементов

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

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

const choices = new Choices('#select', {
  removeItemButton: true,
  maxItemCount: 3
});

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

Поведение интерфейса при достижении лимита

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

  • скрывается возможность выбора дополнительных опций в выпадающем списке;
  • ввод текста поиска (если включён search) перестаёт приводить к добавлению новых значений;
  • визуально элемент сохраняет стандартный вид, но внутренние обработчики блокируют добавление;
  • выбранные элементы остаются доступными для удаления.

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

Управление лимитом через конфигурацию

Основной параметр:

maxItemCount: number

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

Пример отключения ограничения:

const choices = new Choices('#select', {
  removeItemButton: true,
  maxItemCount: -1
});

Динамическое изменение лимита

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

Пример пересоздания экземпляра:

choices.destroy();

const newChoices = new Choices('#select', {
  removeItemButton: true,
  maxItemCount: 5
});

Подход с пересозданием применяется чаще всего, так как внутренние параметры библиотеки не всегда предназначены для прямого runtime-изменения.

Взаимодействие maxItemCount с другими ограничениями

Ограничение количества выбранных элементов может сочетаться с другими параметрами:

  • maxItemText — ограничивает длину отображаемого текста;
  • maxItemCountText — задаёт сообщение при достижении лимита;
  • maxItemSelect (в некоторых реализациях кастомных сборок) — ограничивает выбор внутри группы.

Пример отображения пользовательского сообщения:

const choices = new Choices('#select', {
  removeItemButton: true,
  maxItemCount: 3,
  maxItemCountText: 'Достигнут лимит выбора'
});

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

События при достижении лимита

Хотя библиотека не предоставляет отдельного специализированного события “limit reached”, поведение можно отслеживать через стандартные события изменения состояния:

const choices = new Choices('#select', {
  maxItemCount: 3
});

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

Для более точного контроля используется проверка текущего количества выбранных элементов:

const selectedCount = choices.getValue(true).length;

if (selectedCount >= 3) {
  console.log('Лимит достигнут');
}

Ограничение выбора в динамических списках

При работе с динамически загружаемыми данными (например, AJAX-подгрузкой опций) ограничение продолжает работать независимо от источника данных. Даже если новые элементы добавляются в список, пользователь не сможет превысить установленный лимит.

Пример:

const choices = new Choices('#select', {
  maxItemCount: 2
});

fetch('/api/options')
  .then(res => res.json())
  .then(data => {
    choices.setChoices(data, 'value', 'label', true);
  });

Влияние поиска на ограничение выбора

При включённой функции поиска (searchEnabled) ограничение maxItemCount остаётся активным и распространяется на результаты фильтрации. Это означает, что даже если пользователь сузил список до одного элемента через поиск, превышение лимита всё равно невозможно.

const choices = new Choices('#select', {
  searchEnabled: true,
  maxItemCount: 2
});

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

Работа с программным добавлением элементов

При добавлении значений через API библиотеки ограничение также учитывается. Метод setValue или setChoiceByValue не позволит превысить лимит.

choices.setValue([
  { value: '1', label: 'Первый' },
  { value: '2', label: 'Второй' },
  { value: '3', label: 'Третий' }
]);

Если maxItemCount равен 2, третий элемент не будет добавлен.

Поведение при удалении элементов

Удаление выбранного элемента мгновенно освобождает слот в ограничении. Это реализовано через обновление внутреннего состояния массива выбранных значений.

removeItemButton: true

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

Ограничение в single select режиме

Хотя maxItemCount чаще используется в мультиселектах, в режиме одиночного выбора (removeItem выключен и maxItemCount = 1) он фактически дублирует стандартное поведение select-one, но может применяться для унификации логики компонентов.

const choices = new Choices('#select', {
  maxItemCount: 1
});

Пользовательские сценарии ограничения

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

  • выбор не более N тегов;
  • ограничение списка категорий;
  • контроль количества фильтров в интерфейсе поиска;
  • ограничение состава участников или ролей;
  • предотвращение перегрузки серверной обработки данных.

Каждый из этих сценариев опирается на одну и ту же внутреннюю механику — проверку длины массива выбранных значений перед добавлением нового элемента.

Особенности внутренней реализации

Внутри библиотеки контроль лимита реализован на уровне обработки события добавления элемента. Перед фактическим добавлением выполняется проверка текущего состояния:

  • если количество элементов меньше maxItemCount — добавление разрешено;
  • если равно или превышает — операция отклоняется без изменения DOM.

Такой подход обеспечивает низкую нагрузку и отсутствие необходимости пересчёта DOM после неуспешных попыток добавления.

Ограничение в сочетании с удалёнными опциями

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

choices.removeActiveItems();

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