Ограничения создания

Механизм создания пользовательских опций

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

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

new TomSelect('#select', {
  create: true
});

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


Фильтрация допустимых значений через createFilter

Основной механизм ограничения пользовательского ввода реализуется через createFilter. Это функция, которая определяет, можно ли преобразовать введённую строку в новую опцию.

new TomSelect('#select', {
  create: true,
  createFilter: function(input) {
    return input.length > 2;
  }
});

Фильтр получает строку ввода и должен вернуть true или false. На практике этот механизм используется для:

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

Расширенная версия фильтра часто включает нормализацию:

createFilter: function(input) {
  const value = input.trim().toLowerCase();
  return value.length >= 3 && /^[a-zа-я0-9\s-]+$/i.test(value);
}

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


Контроль дубликатов и уникальности

Tom Select не всегда автоматически предотвращает создание дубликатов. Поведение зависит от режима хранения значений и структуры опций. Ограничение уникальности реализуется через проверку существующих элементов в options и items.

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

createFilter: function(input) {
  const value = input.trim().toLowerCase();

  for (const option in this.options) {
    if (this.options[option].text.toLowerCase() === value) {
      return false;
    }
  }

  return true;
}

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

Дополнительно проверяются выбранные элементы:

if (this.items.includes(value)) return false;

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


Ограничения через createOnBlur и поведение фокуса

Параметр createOnBlur влияет на момент создания нового элемента. Он определяет, будет ли введённое значение автоматически добавлено при потере фокуса.

new TomSelect('#select', {
  create: true,
  createOnBlur: true
});

Ограничения в этом режиме связаны с тем, что:

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

Поэтому часто комбинируется с createFilter, чтобы снизить вероятность некорректных данных.


Управление созданием через функцию create

Наиболее гибкий механизм ограничения — использование функции create, которая заменяет стандартное поведение фабрики новых опций.

new TomSelect('#select', {
  create: function(input, callback) {
    const value = input.trim();

    if (value.length < 3) {
      return callback(null);
    }

    callback({
      value: value,
      text: value
    });
  }
});

Этот вариант позволяет:

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

Асинхронная валидация:

create: function(input, callback) {
  fetch('/validate?value=' + encodeURIComponent(input))
    .then(res => res.json())
    .then(data => {
      if (!data.allowed) return callback(null);

      callback({
        value: data.value,
        text: data.label
      });
    });
}

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


Ограничения через maxItems и контекст выбора

Хотя maxItems напрямую не управляет созданием, он влияет на возможность добавления новых элементов после их создания.

new TomSelect('#select', {
  create: true,
  maxItems: 5
});

В этом режиме:

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

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


Запрет создания через динамическое отключение create

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

const select = new TomSelect('#select', {
  create: true
});

select.settings.create = false;
select.refreshOptions(false);

Подобный подход используется при:

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

Влияние render и нормализации данных

Создание новых элементов тесно связано с функцией render.option и внутренней нормализацией данных. Даже если создание разрешено, отображение может быть изменено или ограничено.

render: {
  option_create: function(data, escape) {
    return `<div class="create-option">Добавить: ${escape(data.input)}</div>`;
  }
}

Несмотря на визуальное отображение, фактическое создание может быть запрещено через createFilter или create.


Ограничение через блокировку символов и очистку ввода

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

createFilter: function(input) {
  const sanitized = input
    .replace(/[^a-zа-я0-9\s]/gi, '')
    .trim();

  return sanitized.length > 0 && sanitized.length <= 20;
}

Такая логика вводит ограничения на:

  • допустимые символы;
  • максимальную длину;
  • формат данных.

Дополнительно может применяться нормализация регистра:

const normalized = input.normalize('NFKC');

Ограничение создания при работе с remote-данными

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

new TomSelect('#select', {
  load: function(query, callback) {
    fetch('/search?q=' + query)
      .then(res => res.json())
      .then(callback);
  },
  create: true,
  createFilter: function(input) {
    return this.hasLoaded; 
  }
});

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


Приоритеты ограничений

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

  1. create — включение механизма;
  2. createFilter — проверка допустимости строки;
  3. create функция — финальная фабрика элемента;
  4. maxItems — ограничение добавления;
  5. внешние состояния (disabled, режим загрузки, права доступа).

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


Конфликты с существующими опциями и их разрешение

При совпадении текста ввода с существующей опцией Tom Select может:

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

Поведение зависит от внутреннего сравнения значений и конфигурации valueField и labelField.

new TomSelect('#select', {
  valueField: 'id',
  labelField: 'name',
  searchField: 'name',
  create: true
});

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


Итоговая структура ограничений

Система ограничений создания в Tom Select формирует многоуровневую модель:

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

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