Режим добавления уникальных значений

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

Контроль повторяющихся значений

Ключевой параметр, отвечающий за уникальность элементов, — duplicateItems. Он задаёт стратегию обработки попыток добавить уже существующее значение в список выбранных элементов.

const choices = new Choices('#select', {
  duplicateItems: false
});

При duplicateItems: false библиотека блокирует повторное добавление идентичного элемента. Идентичность определяется по значению value опции, а не по отображаемому тексту.

При duplicateItems: true повторы разрешены, и один и тот же элемент может быть добавлен многократно, что превращает компонент в поведенчески ближе к «мульти-тегу без ограничений».

Логика определения уникальности

Choices.js использует значение value как основной ключ сравнения. Это означает:

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

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

const choices = new Choices('#select', {
  duplicateItems: false,
  choices: [
    { value: 'js', label: 'JavaScript' },
    { value: 'ts', label: 'TypeScript' },
    { value: 'js', label: 'JavaScript повтор' }
  ]
});

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

Поведение при добавлении через интерфейс

При включённой проверке уникальности ввод через UI проходит несколько стадий:

  1. пользователь вводит значение в поисковое поле
  2. выполняется фильтрация списка доступных опций
  3. при выборе значения проверяется наличие такого value среди выбранных
  4. при совпадении добавление блокируется

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

Добавление через API и уникальность

При программном добавлении через setValue или addItem логика уникальности сохраняется.

choices.setValue([
  { value: 'js', label: 'JavaScript' }
]);

choices.setValue([
  { value: 'js', label: 'JavaScript' }
]);

При duplicateItems: false повторная попытка не изменит состояние компонента.

Метод setValue в этом контексте ведёт себя как «идемпотентная операция» для уже выбранных значений.

Метод addItem и фильтрация дубликатов

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

choices.setChoiceByValue('js');

или:

choices.setValue([{ value: 'js', label: 'JavaScript' }]);

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

  • существует ли уже элемент с таким value
  • разрешены ли дубликаты
  • не превышен ли лимит maxItemCount

Если хотя бы одно условие нарушено, добавление игнорируется.

Взаимодействие с maxItemCount

Уникальность значений часто используется вместе с ограничением количества элементов:

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

При таком сочетании поведение становится детерминированным:

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

Если duplicateItems: true, ограничение maxItemCount перестаёт отражать количество уникальных значений и начинает учитывать фактические добавления, включая повторы.

Поведение при динамическом добавлении опций

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

choices.setChoices([
  { value: 'js', label: 'JavaScript' },
  { value: 'js', label: 'JS alias' }
], 'value', 'label', true);

В таком случае:

  • список опций может содержать повторяющиеся value
  • при выборе будет применяться фильтрация уникальности уже в selected state
  • поведение зависит от конфигурации duplicateItems

Отличие уникальности в UI и внутреннем состоянии

Choices.js разделяет два уровня:

1. UI-уровень

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

2. Data-уровень

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

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

Обработка пользовательского ввода в режиме тегов

В режиме тегирования (tagging input) уникальность становится особенно значимой. При вводе нового значения:

const choices = new Choices('#input', {
  duplicateItems: false,
  addItems: true,
  editItems: false
});

Алгоритм обработки:

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

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

Сравнение строгого и гибкого режима уникальности

Строгий режим (duplicateItems: false)

  • полный запрет повторов value
  • предсказуемое состояние данных
  • подходит для форм, API, фильтров

Гибкий режим (duplicateItems: true)

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

Особенности сравнения значений

Сравнение выполняется без нормализации:

  • строки сравниваются строго (===)
  • регистр учитывается
  • пробелы значимы
{ value: 'JS' }
{ value: 'js' }

Эти значения считаются разными при проверке уникальности.

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

При использовании объектов с дополнительными полями:

{
  value: 'js',
  label: 'JavaScript',
  customProperties: { level: 'advanced' }
}

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

Влияние уникальности на фильтрацию поиска

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

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

Поведение при очистке и повторном добавлении

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

choices.removeActiveItemsByValue('js');
choices.setChoiceByValue('js');

После удаления:

  • value исчезает из выбранных
  • уникальность больше не блокирует добавление
  • состояние возвращается к исходному

Внутренняя модель хранения выбранных значений

Choices.js хранит выбранные элементы в массиве объектов, где каждый объект содержит:

  • value
  • label
  • id
  • дополнительные метаданные

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