Блокировка определенных опций

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

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


Отключение всего компонента

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

const ts = new TomSelect("#select", {
  options: [
    { value: "1", text: "Alpha" },
    { value: "2", text: "Beta" }
  ]
});

// блокировка
ts.disable();

// разблокировка
ts.enable();

Состояние отключения влияет на:

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

Дополнительно состояние синхронизируется с оригинальным <select disabled> при инициализации.


Блокировка отдельных опций через свойство disabled

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

new TomSelect("#select", {
  options: [
    { value: "1", text: "Разрешено" },
    { value: "2", text: "Недоступно", disabled: true },
    { value: "3", text: "Разрешено" }
  ],
  render: {
    option: function(data, escape) {
      return `
        <div class="${data.disabled ? 'disabled' : ''}">
          ${escape(data.text)}
        </div>
      `;
    }
  }
});

Особенности поведения:

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

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

В реальных сценариях состояние доступности часто меняется после загрузки данных или действий пользователя. Tom Select позволяет модифицировать опции после инициализации.

const ts = new TomSelect("#select", { options: [] });

ts.addOption({ value: "1", text: "A" });
ts.addOption({ value: "2", text: "B" });

// обновление опции
ts.updateOption("2", {
  value: "2",
  text: "B",
  disabled: true
});

Если требуется массовая блокировка:

ts.getOption("1").classList.add("disabled");
ts.refreshOptions(false);

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


Перехват добавления через onItemAdd

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

new TomSelect("#select", {
  onItemAdd: function(value, item) {
    if (value === "2") {
      this.removeItem(value);
    }
  }
});

Такой подход применяется, когда:

  • доступность зависит от внешнего состояния
  • данные приходят с сервера без флага disabled
  • требуется сложная бизнес-валидация

Запрет выбора через shouldLoad

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

new TomSelect("#select", {
  load: function(query, callback) {
    fetch(`/api/items?q=${query}`)
      .then(res => res.json())
      .then(data => {
        const filtered = data.filter(item => !item.locked);
        callback(filtered);
      });
  }
});

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


Управление блокировкой через кастомные поля данных

Часто используется расширение модели опции дополнительными атрибутами.

{
  value: "10",
  text: "Premium",
  locked: true
}

Логика блокировки переносится в единый слой:

new TomSelect("#select", {
  onItemAdd: function(value) {
    const option = this.options[value];

    if (option && option.locked) {
      this.removeItem(value);
    }
  }
});

Такой подход упрощает интеграцию с API и серверной валидацией.


Блокировка через optgroup

При группировке опций можно блокировать целые группы значений.

new TomSelect("#select", {
  optgroups: [
    { value: "group1", label: "Доступные" },
    { value: "group2", label: "Заблокированные" }
  ],
  options: [
    { value: "a", text: "A", optgroup: "group1" },
    { value: "b", text: "B", optgroup: "group2", disabled: true }
  ]
});

Это удобно при разделении:

  • активных и архивных данных
  • доступных и запрещённых тарифов
  • разрешённых и системных значений

Визуальная индикация заблокированных элементов

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

render: {
  option: function(data, escape) {
    return `
      <div class="option ${data.disabled ? 'is-disabled' : ''}">
        <span>${escape(data.text)}</span>
      </div>
    `;
  }
}

CSS-слой:

.is-disabled {
  opacity: 0.4;
  pointer-events: none;
}

Это усиливает семантическое соответствие между логикой и интерфейсом.


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

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

const ts = new TomSelect("#select");

document.querySelector("#toggle").addEventListener("change", (e) => {
  if (e.target.checked) {
    ts.updateOption("1", { value: "1", text: "A", disabled: true });
  } else {
    ts.updateOption("1", { value: "1", text: "A", disabled: false });
  }
});

Такая модель используется для:

  • зависимых селектов
  • многошаговых форм
  • конфигурационных интерфейсов

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

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

new TomSelect("#select", {
  maxItems: 1
});

После достижения лимита:

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

Особенности поведения при поиске

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

new TomSelect("#select", {
  score: function(search) {
    return function(item) {
      return item.disabled ? 0 : 1;
    };
  }
});

Или полное исключение из результата:

filter: function(item) {
  return !item.disabled;
}

Смешанные стратегии блокировки

В сложных интерфейсах применяется комбинация методов:

  • disabled: true для базовой блокировки
  • фильтрация на сервере при load
  • проверка в onItemAdd
  • визуальное оформление через render
  • динамическое обновление через updateOption

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