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

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

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

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

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Разработка формы с автосохранением прогресса на сайте
Средняя
от 1 рабочего дня до 3 рабочих дней
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

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

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

Стратегии хранения

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

IndexedDB — то же самое, но для больших данных (файлы, бинарники). Используем через idb или localforage.

Сервер (API) — данные доступны с любого устройства. Требует авторизации или временного токена сессии.

Гибрид — сначала в localStorage (мгновенно), затем синхронизация с сервером в фоне.

Реализация через localStorage

class FormAutoSave {
  constructor(formId, key, debounceMs = 800) {
    this.form = document.getElementById(formId);
    this.key = key;
    this.debounceMs = debounceMs;
    this._timer = null;
    this._init();
  }

  _init() {
    this._restore();
    this.form.addEventListener('input', () => this._schedulesSave());
    this.form.addEventListener('change', () => this._schedulesSave());
    this.form.addEventListener('submit', () => this.clear());
  }

  _schedulesSave() {
    clearTimeout(this._timer);
    this._timer = setTimeout(() => this._save(), this.debounceMs);
  }

  _save() {
    const data = {};
    const elements = this.form.elements;

    for (const el of elements) {
      if (!el.name) continue;
      if (el.type === 'checkbox') {
        data[el.name] = el.checked;
      } else if (el.type === 'radio') {
        if (el.checked) data[el.name] = el.value;
      } else {
        data[el.name] = el.value;
      }
    }

    localStorage.setItem(this.key, JSON.stringify({
      data,
      savedAt: Date.now(),
    }));

    this._updateIndicator('saved');
  }

  _restore() {
    const raw = localStorage.getItem(this.key);
    if (!raw) return;

    const { data, savedAt } = JSON.parse(raw);
    const age = Date.now() - savedAt;
    if (age > 7 * 24 * 60 * 60 * 1000) { // 7 дней — устарело
      this.clear();
      return;
    }

    for (const [name, value] of Object.entries(data)) {
      const el = this.form.elements[name];
      if (!el) continue;
      if (el.type === 'checkbox') el.checked = value;
      else if (el.type === 'radio') {
        const radio = this.form.querySelector(`[name="${name}"][value="${value}"]`);
        if (radio) radio.checked = true;
      } else {
        el.value = value;
      }
    }

    this._updateIndicator('restored');
  }

  clear() {
    localStorage.removeItem(this.key);
  }

  _updateIndicator(state) {
    const el = document.querySelector('[data-autosave-status]');
    if (!el) return;
    el.textContent = state === 'saved' ? 'Сохранено' : 'Черновик восстановлен';
    el.dataset.state = state;
  }
}

// Использование
new FormAutoSave('application-form', 'form_draft_application_v1');

Синхронизация с сервером

Когда пользователь авторизован, черновик нужно сохранять на сервере:

async function syncDraftToServer(formKey, data) {
  try {
    await fetch('/api/drafts', {
      method: 'PUT',
      headers: {
        'Content-Type': 'application/json',
        'X-CSRF-TOKEN': window.csrfToken,
      },
      body: JSON.stringify({ key: formKey, data }),
    });
  } catch {
    // Fallback — оставляем в localStorage, попробуем позже
  }
}

На Laravel:

// routes/api.php
Route::middleware('auth')->group(function () {
    Route::put('/drafts', [DraftController::class, 'store']);
    Route::get('/drafts/{key}', [DraftController::class, 'show']);
    Route::delete('/drafts/{key}', [DraftController::class, 'destroy']);
});

// DraftController
public function store(Request $request)
{
    Draft::updateOrCreate(
        ['user_id' => auth()->id(), 'key' => $request->key],
        ['data' => $request->data, 'expires_at' => now()->addDays(30)]
    );
    return response()->noContent();
}

Индикатор состояния

Пользователь должен видеть, когда форма сохранена. Три состояния: «Сохраняется...», «Сохранено N минут назад», «Ошибка сохранения».

// React-вариант
function AutoSaveIndicator({ status, savedAt }) {
  const labels = {
    saving: 'Сохраняется...',
    saved: savedAt ? `Сохранено ${formatRelative(savedAt)}` : 'Сохранено',
    error: 'Ошибка сохранения',
    idle: '',
  };

  return (
    <span className={`autosave-badge autosave-badge--${status}`}>
      {labels[status]}
    </span>
  );
}

Многошаговые формы (wizard)

Для wizard-форм сохраняем не только данные полей, но и текущий шаг:

const state = {
  step: currentStep,
  fields: collectFields(),
  completedSteps: [1, 2, 3],
};
localStorage.setItem('wizard_draft', JSON.stringify(state));

При восстановлении спрашиваем пользователя: «Продолжить с шага 3 или начать заново?» — модальное окно с двумя кнопками.

Конфликты при параллельном редактировании

Если форма открыта в нескольких вкладках, используем localStorage event для синхронизации:

window.addEventListener('storage', (e) => {
  if (e.key === 'form_draft_application_v1') {
    const remote = JSON.parse(e.newValue);
    if (remote.savedAt > localSavedAt) {
      applyRemoteData(remote.data);
    }
  }
});

Сроки

Автосохранение в localStorage с восстановлением и индикатором — 2–3 рабочих дня. С серверной синхронизацией, поддержкой wizard, конфликт-резолюцией и историей черновиков — 5–7 дней.