Обработка сброса формы

Сброс формы в связке с Awesomplete затрагивает не только очистку текстового поля, но и синхронизацию внутреннего состояния автодополнения, пользовательского выбора и связанных скрытых данных. При использовании компонента в формах HTML поведение по умолчанию часто оказывается недостаточным: стандартный form.reset() очищает значения инпутов, но не учитывает кэшированные состояния, выбранные элементы и пользовательские расширения логики.

Awesomplete не управляет формой напрямую и не перехватывает событие reset. Это означает, что при вызове:

form.reset();

браузер:

  • очищает значения <input>
  • возвращает значения к defaultValue
  • не вызывает специальные методы библиотеки
  • не сбрасывает пользовательские состояния расширений

В результате визуально поле очищается, но:

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

Базовая синхронизация с событием reset

Корректная обработка сброса формы требует явного перехвата события:

const input = document.querySelector("#city");
const awesomplete = new Awesomplete(input);

input.form.addEventListener("reset", () => {
    awesomplete.close();
});

Метод close() закрывает выпадающий список, но не очищает значение поля. Поэтому при сбросе формы требуется дополнительно учитывать очистку значения.

Расширенный вариант:

input.form.addEventListener("reset", () => {
    awesomplete.close();
    input.value = "";
});

Здесь устраняется расхождение между состоянием формы и UI компонента.

Сброс выбранного значения и события выбора

При использовании событий выбора:

  • awesomplete-select
  • awesomplete-selectcomplete

часто сохраняется внешняя модель данных, например:

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

В таком случае form.reset() не очищает hiddenInput. Требуется явная синхронизация:

input.form.addEventListener("reset", () => {
    awesomplete.close();
    input.value = "";
    hiddenInput.value = "";
});

Работа с defaultValue и восстановлением состояния

В некоторых сценариях важно не просто очистить поле, а восстановить исходное значение формы. У HTMLInputElement есть свойство defaultValue, которое используется при reset.

Если требуется согласованность с Awesomplete, необходимо учитывать оба состояния:

input.form.addEventListener("reset", () => {
    setTimeout(() => {
        awesomplete.close();

        if (input.value !== input.defaultValue) {
            input.value = input.defaultValue;
        }
    });
});

Использование setTimeout связано с тем, что событие reset происходит до завершения стандартного восстановления значений браузером.

Сброс в режиме кастомного списка (multiple values)

При реализации множественного выбора через токены (например, разделённые значения в одном поле или отдельные элементы DOM), сброс формы становится многокомпонентной операцией:

input.form.addEventListener("reset", () => {
    awesomplete.close();

    input.value = "";

    document.querySelectorAll(".tag-item")
        .forEach(el => el.remove());
});

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

hiddenInput.value = "";
selectedItems.length = 0;

Состояние автодополнения должно быть приведено к начальному синхронно с DOM.

Перехват очистки через mutation логики

Awesomplete не предоставляет встроенного события reset, поэтому часто используется наблюдение за изменением значения:

input.addEventListener("input", () => {
    if (input.value === "") {
        awesomplete.close();
    }
});

Такой подход полезен, если сброс формы происходит не только через кнопку reset, но и программно:

form.reset();
input.value = "";
input.dispatchEvent(new Event("input"));

Поведение при программном сбросе

При программной очистке формы важно учитывать порядок вызовов:

form.reset();

и

awesomplete.close();

Если вызвать close() до reset(), браузер может снова открыть список при восстановлении фокуса или значения.

Корректный порядок:

form.addEventListener("reset", () => {
    awesomplete.close();

    requestAnimationFrame(() => {
        input.value = "";
    });
});

requestAnimationFrame позволяет дождаться завершения внутреннего обновления DOM.

Очистка списка и источника данных

Если список подсказок динамический:

awesomplete.list = [];

или обновляется из API, сброс формы может требовать возврата к начальному состоянию:

input.form.addEventListener("reset", () => {
    awesomplete.close();
    awesomplete.list = initialList;
});

Это особенно важно при фильтрации данных, когда список зависит от внешнего контекста формы.

Интеграция с валидацией формы

При наличии кастомной валидации reset не сбрасывает визуальные ошибки:

input.classList.remove("error");
input.setCustomValidity("");

Комбинированный сброс:

input.form.addEventListener("reset", () => {
    awesomplete.close();

    input.classList.remove("error");
    input.setCustomValidity("");

    hiddenInput.value = "";
});

Поведение при потере фокуса после reset

После form.reset() браузер может автоматически возвращать фокус в первый input формы. Если Awesomplete список был открыт, возможен визуальный артефакт.

Стабилизирующее решение:

input.form.addEventListener("reset", () => {
    awesomplete.close();

    setTimeout(() => {
        input.blur();
    });
});

Сброс через кнопку и через JS-логику

Разные источники сброса требуют одинакового поведения:

  • кнопка <button type="reset">
  • form.reset()
  • кастомная функция очистки

Унифицированный подход:

function resetAutocompleteForm(form, awesomplete, input, hiddenInput) {
    awesomplete.close();
    input.value = "";
    hiddenInput.value = "";
}

И привязка:

form.addEventListener("reset", () => {
    resetAutocompleteForm(form, awesomplete, input, hiddenInput);
});

Такой слой абстракции исключает рассинхронизацию состояния между UI и данными.

Поведение при асинхронных источниках данных

Если список подсказок загружается асинхронно:

fetch("/cities")
    .then(r => r.json())
    .then(data => awesomplete.list = data);

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

input.form.addEventListener("reset", () => {
    awesomplete.close();

    awesomplete.list = [];

    fetch("/cities")
        .then(r => r.json())
        .then(data => {
            awesomplete.list = data;
        });
});

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