Валидация множественного ввода

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

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


Разделение строки на токены перед валидацией

Первый этап валидации — нормализация ввода. Строка преобразуется в массив значений:

function splitValues(input) {
    return input
        .split(',')
        .map(v => v.trim())
        .filter(Boolean);
}

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

При интеграции с Awesomplete этот этап часто выполняется либо в обработчиках событий input, либо в кастомной функции replace.


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

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

function isValidValue(value, allowedValues) {
    return allowedValues.includes(value);
}

Для более сложных сценариев используется нормализация регистра:

function isValidValue(value, allowedValues) {
    const normalized = value.toLowerCase();
    return allowedValues.some(v => v.toLowerCase() === normalized);
}

В контексте Awesomplete такая проверка часто применяется в функции filter, которая определяет, какие элементы отображаются в списке подсказок.


Исключение дубликатов

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

function removeDuplicates(values) {
    return [...new Set(values)];
}

Более гибкий вариант учитывает регистр и пробелы:

function normalize(value) {
    return value.trim().toLowerCase();
}

function removeDuplicates(values) {
    const seen = new Set();
    return values.filter(v => {
        const key = normalize(v);
        if (seen.has(key)) return false;
        seen.add(key);
        return true;
    });
}

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


Валидация через регулярные выражения

Для строгих форматов (email, коды, идентификаторы) применяется проверка через регулярные выражения:

const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

function validateEmail(value) {
    return emailPattern.test(value);
}

Если ввод представляет собой список email-адресов, проверка выполняется для каждого токена:

function validateAll(values) {
    return values.every(validateEmail);
}

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


Интеграция в механизм автодополнения

Awesomplete предоставляет несколько точек расширения, которые используются для валидации:

  • filter — управление отображением подсказок
  • item — кастомизация элемента списка
  • replace — управление вставкой выбранного значения
  • selectcomplete — обработка завершённого выбора

Наиболее важная логика множественной валидации обычно сосредоточена в replace:

awesomplete.replace = function (suggestion) {
    const values = splitValues(input.value);

    values.pop();
    values.push(suggestion.label);

    const cleaned = removeDuplicates(values);

    input.value = cleaned.join(", ");
};

Таким образом, каждое новое значение проходит через цепочку нормализации и проверки.


Блокировка некорректного выбора

Иногда требуется полностью запретить добавление значений, не прошедших проверку. В этом случае используется контроль в select или selectcomplete:

input.addEventListener("awesomplete-selectcomplete", function (e) {
    const value = e.text.value;

    if (!isValidValue(value, allowedValues)) {
        e.preventDefault();
    }
});

В рамках Awesomplete такой подход позволяет перехватывать момент вставки и предотвращать загрязнение данных.


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

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

async function validateOnServer(value) {
    const res = await fetch(`/validate?q=${encodeURIComponent(value)}`);
    const data = await res.json();
    return data.valid;
}

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

async function validateValues(values) {
    const results = await Promise.all(values.map(validateOnServer));
    return results.every(Boolean);
}

В таких сценариях Awesomplete выступает только как слой интерфейса, а вся бизнес-логика переносится на серверную часть.


Подсветка ошибок на уровне UI

Валидация должна сопровождаться визуальной обратной связью. Распространённый подход — добавление CSS-классов:

function markInvalid(input) {
    input.classList.add("invalid");
}

function markValid(input) {
    input.classList.remove("invalid");
}

При проверке списка:

if (!validateAll(values)) {
    markInvalid(input);
} else {
    markValid(input);
}

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


Контроль границ количества элементов

Множественный ввод часто ограничивается максимальным количеством значений:

const MAX_ITEMS = 5;

function isWithinLimit(values) {
    return values.length <= MAX_ITEMS;
}

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

awesomplete.replace = function (suggestion) {
    const values = splitValues(input.value);

    if (values.length >= MAX_ITEMS) return;

    values.push(suggestion.label);
    input.value = values.join(", ");
};

В Awesomplete такие ограничения особенно важны при работе с тегами и фильтрами.


Комбинированная схема валидации

Полноценная система проверки включает несколько уровней:

  1. Синтаксическое разбиение строки
  2. Удаление пустых значений
  3. Проверка формата
  4. Проверка по справочнику
  5. Удаление дубликатов
  6. Ограничение количества
  7. Серверная проверка при необходимости

Эта цепочка обеспечивает устойчивое поведение интерфейса даже при сложных сценариях множественного выбора в Awesomplete.