Сброс и очистка формы в JavaScript

Сброс и очистка формы - не одно и то же. Метод reset() возвращает полям значения, заданные при загрузке страницы. Если поле изначально было заполнено или отмечено, после сброса это состояние восстановится.

Полная очистка означает другое: текстовые поля должны стать пустыми, checkbox и radio - неотмеченными, а в списках не должно остаться выбранного значения. Для этого поля изменяют вручную.

Форма для примеров

Создадим форму профиля с начальными значениями:

<form class="profile-form">
  <label>
    Имя
    <input name="username" type="text" value="Анна">
  </label>

  <label>
    О себе
    <textarea name="about" rows="4">Изучаю JavaScript</textarea>
  </label>

  <label>
    Город
    <select name="city">
      <option value="moscow" selected>Москва</option>
      <option value="kazan">Казань</option>
      <option value="samara">Самара</option>
    </select>
  </label>

  <label>
    <input name="newsletter" type="checkbox" checked>
    Получать рассылку
  </label>

  <fieldset>
    <legend>Тема оформления</legend>

    <label>
      <input name="theme" type="radio" value="light" checked>
      Светлая
    </label>

    <label>
      <input name="theme" type="radio" value="dark">
      Тёмная
    </label>
  </fieldset>

  <label>
    Аватар
    <input name="avatar" type="file" accept="image/*">
  </label>

  <button type="submit">Сохранить</button>
  <button type="reset">Вернуть исходные значения</button>
  <button class="clear-form" type="button">Очистить форму</button>
</form>

<p class="form-status" aria-live="polite"></p>

При загрузке формы в поле имени находится «Анна», в textarea - текст о JavaScript, выбран город Москва, установлены флажок рассылки и светлая тема. Эти значения считаются исходными.

Сброс формы через reset()

Получим форму и вызовем метод reset():

const profileForm = document.querySelector('.profile-form');

profileForm.reset();

Метод возвращает элементы управления к исходному состоянию:

  • в поле имени снова появится «Анна»;
  • textarea снова будет содержать «Изучаю JavaScript»;
  • в списке будет выбрана Москва;
  • checkbox рассылки снова станет отмеченным;
  • в radio-группе снова будет выбрана светлая тема;
  • выбранный файл будет удалён из поля.

Поэтому reset() нельзя считать методом полной очистки. Его результат зависит от начальной разметки формы.

Не задавайте элементу формы name=“reset” или id=“reset”. Такой элемент может перекрыть одноимённый метод, и вызов profileForm.reset() перестанет работать.

Кнопка type=“reset”

Сброс можно выполнить без JavaScript с помощью кнопки:

<button type="reset">Вернуть исходные значения</button>

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

<form id="settings-form">
  <!-- поля -->
</form>

<button type="reset" form="settings-form">
  Вернуть исходные значения
</button>

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

Какие значения восстанавливает reset()

Метод работает с состоянием элементов формы, но не отменяет любые изменения на странице.

ЭлементРезультат сброса
Текстовый inputВозвращается начальный value
textareaВозвращается исходный текст
Checkbox и radioВосстанавливается начальное состояние checked
selectВосстанавливаются пункты с начальным selected
input type=“file”Выбранные файлы удаляются из поля

reset() не удаляет добавленные CSS-классы, не скрывает открытые блоки, не очищает отдельные сообщения и не возвращает изменённый HTML. Такое состояние создаётся вашим кодом вне стандартных значений полей, поэтому его нужно обновлять отдельно.

Свойства disabled и readonly также не возвращаются к исходным значениям. Если JavaScript включил или отключил поле, сброс формы сам по себе это изменение не отменит.

Свойства defaultValue, defaultChecked и defaultSelected

В DOM начальное и текущее состояния хранятся отдельно:

const usernameInput = profileForm.elements.username;
const newsletterCheckbox = profileForm.elements.newsletter;
const citySelect = profileForm.elements.city;
const moscowOption = citySelect.options[0];

console.log(usernameInput.value); // текущее значение
console.log(usernameInput.defaultValue); // Анна

console.log(newsletterCheckbox.checked); // текущее состояние
console.log(newsletterCheckbox.defaultChecked); // true

console.log(moscowOption.selected); // текущее состояние
console.log(moscowOption.defaultSelected); // true

value, checked и selected показывают состояние, которое видит пользователь сейчас. Свойства с приставкой default содержат значения, к которым форма вернётся после reset().

Исходное значение можно изменить из JavaScript. Например, после следующего кода сброс будет возвращать имя «Мария»:

usernameInput.defaultValue = 'Мария';
profileForm.reset();

console.log(usernameInput.value); // Мария

Изменять свойства defaultValue, defaultChecked и defaultSelected следует только тогда, когда действительно нужно задать новую точку сброса. Для обычного изменения текущего значения используют value, checked и selected.

Событие reset

При сбросе возникает событие reset на форме. Оно срабатывает и для кнопки type=“reset”, и при вызове метода reset():

const formStatus = document.querySelector('.form-status');

profileForm.addEventListener('reset', function () {
  formStatus.textContent = 'Исходные значения восстановлены';
});

Событие можно отменить. Например, перед сбросом длинной формы можно запросить подтверждение:

profileForm.addEventListener('reset', function (event) {
  const shouldReset = confirm('Вернуть исходные значения?');

  if (!shouldReset) {
    event.preventDefault();
  }
});

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

Сброс не вызывает события input и change у каждого поля. Если другая часть интерфейса зависит от их значений, обновите её в обработчике reset.

Полная очистка формы

Чтобы сделать все поля пустыми независимо от начальных значений, изменим их текущее состояние вручную:

const clearFormButton = document.querySelector('.clear-form');

function clearProfileForm() {
  profileForm.elements.username.value = '';
  profileForm.elements.about.value = '';
  profileForm.elements.city.selectedIndex = -1;
  profileForm.elements.newsletter.checked = false;
  profileForm.elements.avatar.value = '';

  const themeRadios = profileForm.querySelectorAll(
    'input[name="theme"]',
  );

  themeRadios.forEach(function (radio) {
    radio.checked = false;
  });
}

clearFormButton.addEventListener('click', clearProfileForm);

Для текстовых полей используется пустая строка, для checkbox и radio - checked = false. Значение selectedIndex = -1 снимает выбор со всех пунктов обычного select.

Если в списке есть специальный пункт с value="", вместо индекса удобнее выбрать его явно:

profileForm.elements.city.value = '';

У select multiple нужно снять свойство selected у каждого пункта:

const multipleOptions = profileForm.querySelectorAll(
  'select[multiple] option',
);

for (const option of multipleOptions) {
  option.selected = false;
}

Полю type=“file” разрешено присвоить пустую строку, чтобы убрать выбранные файлы. Установить произвольный путь к файлу через JavaScript нельзя.

Ручное изменение значений, как и reset(), само по себе не вызывает события input и change.

Очистка ошибок и состояния интерфейса

Форма может содержать сообщения ошибок, атрибуты aria-invalid и пользовательские ошибки из setCustomValidity(). Метод reset() не управляет этим состоянием.

Создадим отдельную функцию очистки:

function clearFormState() {
  const fields = profileForm.querySelectorAll(
    'input, textarea, select',
  );

  fields.forEach(function (field) {
    field.setCustomValidity('');
    field.removeAttribute('aria-invalid');
  });

  const errorElements = profileForm.querySelectorAll('.field-error');

  errorElements.forEach(function (errorElement) {
    errorElement.textContent = '';
  });

  formStatus.textContent = '';
}

Функция очищает пользовательские ошибки, оформление невалидных полей, сообщения рядом с ними и общий статус. Её можно вызвать вместе со сбросом или полной очисткой.

profileForm.reset();
clearFormState();

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

Очистка после успешной отправки

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

profileForm.addEventListener('submit', async function (event) {
  event.preventDefault();

  try {
    const response = await fetch('/api/profile', {
      method: 'POST',
      body: new FormData(profileForm),
    });

    if (!response.ok) {
      throw new Error('Не удалось сохранить данные');
    }

    profileForm.reset();
    clearFormState();
    formStatus.textContent = 'Данные сохранены';
  } catch (error) {
    formStatus.textContent = 'Не удалось сохранить данные';
  }
});

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

В форме из примера reset() вернёт начальные значения, а не сделает поля пустыми. Если после успешной отправки нужна полная очистка, вместо него вызовите clearProfileForm().

Итого

Метод form.reset() и кнопка type=“reset” возвращают поля к значениям по умолчанию. Эти значения доступны через defaultValue, defaultChecked и defaultSelected. Сброс можно отследить и отменить через событие reset.

Для полной очистки задайте пустые значения вручную, учитывая тип каждого поля. Сообщения валидации, атрибуты, CSS-классы и зависимые блоки интерфейса очищаются отдельно. После отправки изменяйте форму только после успешного ответа, чтобы пользователь не потерял введённые данные при ошибке.