Работа с элементами form

Работа автодополнения в контексте HTML-форм требует не только отображения подсказок, но и корректного управления значениями инпутов, синхронизации состояния, а также подготовки данных к отправке. В связке с формами Awesomplete выступает как слой UI-логики, не вмешиваясь в механизм сабмита, но изменяя поведение полей ввода.

Основная идея использования заключается в привязке экземпляра Awesomplete к стандартному <input> внутри <form>, после чего управление значениями остаётся за браузерной формой, а библиотека отвечает за удобство ввода.


Базовая привязка к input внутри form

Структура формы остаётся стандартной:

<form id="searchForm">
  <input id="cityInput" name="city" />
  <button type="submit">Отправить</button>
</form>

Инициализация Awesomplete выполняется напрямую на поле:

const input = document.querySelector("#cityInput");

const awesomplete = new Awesomplete(input, {
  list: ["Almaty", "Astana", "Shymkent", "Karaganda"]
});

Поведение формы при этом не меняется: значение поля отправляется как обычно через name="city".


Синхронизация отображаемого текста и отправляемого значения

В типичной реализации отображаемое значение совпадает с отправляемым. Однако часто требуется разделение UI-значения и фактического идентификатора.

Использование пар «label / value»

const cities = [
  { label: "Almaty", value: "ALA" },
  { label: "Astana", value: "NQZ" },
  { label: "Karaganda", value: "KGF" }
];

const awesomplete = new Awesomplete(input, {
  list: cities.map(c => c.label)
});

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

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

  const city = cities.find(c => c.label === selectedLabel);
  input.dataset.value = city ? city.value : "";
});

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


Использование скрытого поля для отправки ID

Часто требуется отправка не текста, а идентификатора. Тогда структура формы расширяется:

<form id="cityForm">
  <input id="cityInput" autocomplete="off" />
  <input type="hidden" name="city_id" id="cityId" />
  <button type="submit">Send</button>
</form>

Связка реализуется через событие выбора:

const input = document.querySelector("#cityInput");
const hidden = document.querySelector("#cityId");

const cities = [
  { label: "Almaty", value: "ALA" },
  { label: "Astana", value: "NQZ" }
];

new Awesomplete(input, {
  list: cities.map(c => c.label)
});

input.addEventListener("awesomplete-selectcomplete", function (e) {
  const selected = cities.find(c => c.label === e.text.value);
  hidden.value = selected ? selected.value : "";
});

Такой подход отделяет UI-слой от слоя данных формы.


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

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

const form = document.querySelector("#cityForm");

form.addEventListener("submit", function (e) {
  const value = input.value;

  const exists = cities.some(c => c.label === value);

  if (!exists) {
    e.preventDefault();
    hidden.value = "";
  }
});

Подобная проверка предотвращает отправку невалидных значений.


Принудительное ограничение значений формы

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

input.addEventListener("blur", function () {
  const match = cities.some(c => c.label === input.value);

  if (!match) {
    input.value = "";
    hidden.value = "";
  }
});

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


Использование нескольких Awesomplete в одной форме

Формы часто содержат несколько полей с автодополнением, например город и страна.

<form id="geoForm">
  <input id="country" name="country" />
  <input id="city" name="city" />
</form>
new Awesomplete(document.querySelector("#country"), {
  list: ["Kazakhstan", "Russia", "China"]
});

new Awesomplete(document.querySelector("#city"), {
  list: ["Almaty", "Moscow", "Beijing"]
});

Каждое поле работает независимо, но при необходимости возможна зависимая логика.


Зависимые поля формы

Сценарий «страна → города» требует динамического обновления списка.

const data = {
  Kazakhstan: ["Almaty", "Astana", "Karaganda"],
  Russia: ["Moscow", "Kazan", "Sochi"]
};

const countryInput = document.querySelector("#country");
const cityInput = document.querySelector("#city");

const cityAwesomplete = new Awesomplete(cityInput, {
  list: []
});

countryInput.addEventListener("awesomplete-selectcomplete", function (e) {
  const cities = data[e.text.value] || [];

  cityAwesomplete.list = cities;
});

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


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

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

countryInput.addEventListener("input", function () {
  cityInput.value = "";
});

Это предотвращает ситуацию, когда выбранный город не соответствует выбранной стране.


Работа с событием выбора и отправкой формы

Awesomplete предоставляет событие awesomplete-selectcomplete, которое фиксирует финальный выбор пользователя. Это событие используется как точка синхронизации состояния формы.

input.addEventListener("awesomplete-selectcomplete", function (e) {
  console.log("Выбран элемент:", e.text.value);
});

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


Управление значением через программное API

В некоторых сценариях значение формы задаётся программно, например при редактировании записи.

input.value = "Almaty";
hidden.value = "ALA";

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


Очистка формы и сброс Awesomplete

При сбросе формы требуется очистить не только поля, но и связанные состояния.

form.addEventListener("reset", function () {
  hidden.value = "";
});

Awesomplete не хранит внутреннего состояния формы, поэтому достаточно очистки связанных значений.


Обработка submit без перезагрузки

В SPA-сценариях форма часто перехватывается:

form.addEventListener("submit", function (e) {
  e.preventDefault();

  const payload = {
    city: hidden.value
  };

  fetch("/api", {
    method: "POST",
    body: JSON.stringify(payload)
  });
});

В этом случае Awesomplete влияет только на ввод, не участвуя в отправке данных напрямую.


Итоговая модель поведения в форме

Awesomplete в контексте форм функционирует как слой улучшения UX над стандартными <input>:

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

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