Валидация на стороне клиента в связке с Awesomplete строится вокруг контроля двух уровней: ограничения допустимых значений на этапе выбора из подсказок и проверки итогового значения перед отправкой формы. Библиотека сама по себе отвечает только за автодополнение и фильтрацию списка, поэтому вся логика допустимости вводимых данных реализуется через стандартные механизмы JavaScript и HTML-инпутов, дополняемые событиями Awesomplete.
Awesomplete работает поверх обычного <input> и не
блокирует ввод произвольного текста. Это означает, что без
дополнительной логики пользователь может ввести значение, отсутствующее
в списке. Основная задача валидации — синхронизировать:
list)Ключевая идея заключается в том, что валидным считается только значение, выбранное из списка Awesomplete, а не любое совпадающее текстово.
Самый прямой способ валидации — сравнение значения input с источником данных автодополнения.
const allowedValues = ["Apple", "Apricot", "Banana", "Blueberry"];
const input = document.querySelector("#fruit");
const awesomplete = new Awesomplete(input, {
list: allowedValues
});
Далее добавляется функция проверки:
function isValidValue(value) {
return allowedValues.includes(value);
}
Такой подход является базовым, но не учитывает поведение пользователя при ручном вводе. Поэтому он дополняется обработкой событий.
Awesomplete предоставляет событие выбора элемента через
awesomplete-selectcomplete. Оно является ключевой точкой
фиксации валидного значения.
input.addEventListener("awesomplete-selectcomplete", function () {
input.dataset.valid = "true";
});
После выбора из списка значение можно считать валидным без дополнительных проверок.
При любом изменении input состояние валидности должно сбрасываться, поскольку пользователь может изменить уже корректное значение.
input.addEventListener("input", function () {
input.dataset.valid = "false";
});
Таким образом формируется простая модель состояния:
true — значение выбрано из Awesompletefalse — значение изменено вручную или не
подтвержденоОдним из ключевых моментов является событие blur, где
происходит окончательная проверка.
input.addEventListener("blur", function () {
if (!isValidValue(input.value)) {
input.value = "";
input.classList.add("invalid");
} else {
input.classList.remove("invalid");
}
});
Такой подход гарантирует, что даже если пользователь не выбрал элемент из списка, а ввёл его вручную, значение будет отклонено.
В некоторых сценариях требуется полностью запретить любые значения, кроме предложенных. В этом случае используется комбинация проверки и принудительного очищения поля.
input.addEventListener("awesomplete-selectcomplete", function () {
input.dataset.valid = "true";
});
input.addEventListener("input", function () {
input.dataset.valid = "false";
});
И финальная проверка перед отправкой:
form.addEventListener("submit", function (e) {
if (!isValidValue(input.value)) {
e.preventDefault();
input.classList.add("invalid");
}
});
Awesomplete хорошо сочетается с нативными механизмами HTML5, такими
как required, pattern и
setCustomValidity.
<input id="fruit" required>
input.addEventListener("input", function () {
if (!isValidValue(input.value)) {
input.setCustomValidity("Недопустимое значение");
} else {
input.setCustomValidity("");
}
});
Такой механизм позволяет использовать стандартный UI браузера для отображения ошибок.
Когда список значений динамический или частично структурированный, используется регулярная проверка.
const pattern = /^[A-Z][a-z]+$/;
function isValidValue(value) {
return pattern.test(value);
}
Awesomplete при этом остаётся только инструментом подсказок, а не источником истины.
Проблема валидации часто связана с различием регистра, пробелов и формата. Поэтому ввод нормализуется перед проверкой.
function normalize(value) {
return value.trim().toLowerCase();
}
function isValidValue(value) {
return allowedValues
.map(v => v.toLowerCase())
.includes(normalize(value));
}
Нормализация позволяет устранить ложные несоответствия при визуально идентичных значениях.
В некоторых интерфейсах требуется поведение, при котором пользователь может только выбирать элементы из списка. Это реализуется через блокировку неподтверждённых значений.
input.addEventListener("keydown", function (e) {
if (e.key === "Enter") {
const match = allowedValues.includes(input.value);
if (!match) {
e.preventDefault();
}
}
});
Дополнительно можно очищать поле при некорректном вводе:
input.addEventListener("blur", function () {
if (!allowedValues.includes(input.value)) {
input.value = "";
}
});
При использовании Awesomplete для тегов или множественных значений ввод разбивается на части.
const input = document.querySelector("#tags");
function splitValues(value) {
return value.split(",").map(v => v.trim()).filter(Boolean);
}
Проверка каждого элемента:
function areValid(values) {
return values.every(v => allowedValues.includes(v));
}
В этом сценарии Awesomplete работает только на уровне последнего токена, а валидация охватывает весь массив.
Финальный слой проверки всегда располагается на уровне формы, так как пользователь может обойти любые клиентские события.
form.addEventListener("submit", function (e) {
const values = splitValues(input.value);
if (!areValid(values)) {
e.preventDefault();
input.classList.add("invalid");
}
});
Это обеспечивает целостность данных независимо от поведения UI.
При изменении источника данных список Awesomplete может обновляться, что требует пересчёта валидных значений.
awesomplete.list = newValues;
После обновления важно сбросить текущее состояние:
input.dataset.valid = "false";
Если этого не сделать, ранее валидные значения могут стать недопустимыми, оставаясь в поле.
При загрузке списка с сервера валидность определяется только после завершения запроса.
fetch("/api/fruits")
.then(res => res.json())
.then(data => {
awesomplete.list = data;
allowedValues = data;
});
Во время загрузки ввод либо блокируется, либо помечается как временно невалидный.
input.disabled = true;
После загрузки:
input.disabled = false;
Awesomplete генерирует несколько событий, которые используются для контроля состояния:
awesomplete-openawesomplete-closeawesomplete-selectawesomplete-selectcompleteНаиболее важным для валидации является
awesomplete-selectcomplete, так как он фиксирует итоговое
значение после выбора.
input.addEventListener("awesomplete-selectcomplete", function () {
input.setCustomValidity("");
});
Валидация обычно сопровождается визуальным состоянием поля.
input.invalid {
border-color: red;
background-color: #ffecec;
}
Изменение класса происходит синхронно с логикой проверки:
function markInvalid(state) {
input.classList.toggle("invalid", !state);
}
В сложных формах Awesomplete используется вместе с другими источниками ввода. В этом случае валидация строится по принципу приоритетов:
Такая многоуровневая схема позволяет исключить расхождения между UI и бизнес-логикой.
Awesomplete не хранит состояние валидности, поэтому оно дублируется в отдельной переменной.
let state = {
valid: false,
value: ""
};
Обновление состояния:
input.addEventListener("awesomplete-selectcomplete", function () {
state.valid = true;
state.value = input.value;
});
Такой подход позволяет отделить UI-слой от логики валидации и использовать единый источник истины при обработке формы.