Corp/LIVE_VALIDATION_GUIDE.md
Игорь Надеин 7cfd290d7d feat(requests): Этапы 1-2 - добавлены поля получателей в модель и сериализаторы
- Добавлены ManyToMany поля: departments, recipients, cc_users, sent_to_all_department
- Старое поле department сохранено для обратной совместимости
- Создана миграция с автоматическим переносом данных
- Обновлены сериализаторы RequestReadSerializer и RequestWriteSerializer
- Добавлен RecipientIDsField для поддержки разных форматов
- Добавлены методы is_recipient, add_recipient, remove_recipient в модель
- Добавлена валидация получателей и отделов
2025-12-02 17:15:04 +03:00

8.4 KiB
Raw Blame History

Live Validation - Валидация формы в реальном времени

Описание

Модуль liveValidationHandler.js обеспечивает валидацию формы прямо в процессе ввода данных пользователем. Поля подсвечиваются зелёным (валидны) или красным (ошибки) с отображением сообщений об ошибках.

Особенности

✅ Валидация в реальном времени - проверка при вводе с debounce
✅ Валидация при потере фокуса - проверка когда пользователь покидает поле
✅ Валидация при отправке - финальная проверка перед submit
✅ Красивая подсветка - использует Bootstrap классы .is-valid / .is-invalid
✅ Умное поведение - валидация начинается только после первого касания поля
✅ Debounce - не спамит проверками при быстром вводе
✅ Связанные поля - автоматически ревалидирует зависимые поля (например, password2 при изменении password1)

Типы валидаторов

1. required - Обязательное поле

{ type: 'required', message: 'Поле обязательно для заполнения' }

2. email - Email формат

{ type: 'email', message: 'Введите корректный email' }

3. pattern - Регулярное выражение

{ 
  type: 'pattern', 
  pattern: /^\+?\d{10,15}$/, 
  message: 'Неверный формат телефона' 
}

4. minLength / maxLength - Длина строки

{ type: 'minLength', value: 6, message: 'Минимум 6 символов' }
{ type: 'maxLength', value: 100, message: 'Максимум 100 символов' }

5. match - Совпадение с другим полем

{ 
  type: 'match', 
  field: 'password1', 
  message: 'Пароли не совпадают' 
}

6. anyContact - Хотя бы одно из полей заполнено

{
  type: 'anyContact',
  fields: ['telegram', 'whatsapp', 'wechat'],
  message: 'Заполните хотя бы один мессенджер'
}

7. custom - Кастомная функция валидации

{
  type: 'custom',
  validate: (value, formData, input) => {
    const date = new Date(value);
    const age = new Date().getFullYear() - date.getFullYear();
    return age >= 18 && age <= 100;
  },
  message: 'Возраст должен быть от 18 до 100 лет'
}

Использование

Базовая инициализация

import { initLiveValidation } from './liveValidationHandler.js';

const validator = initLiveValidation({
  formSelector: '#myForm',
  rules: {
    email: [
      { type: 'required', message: 'Email обязателен' },
      { type: 'email', message: 'Некорректный email' }
    ],
    password: [
      { type: 'required', message: 'Пароль обязателен' },
      { type: 'minLength', value: 6, message: 'Минимум 6 символов' }
    ]
  }
});

Расширенная конфигурация

const validator = initLiveValidation({
  formSelector: 'form',
  debounce: 500,           // Задержка перед валидацией (мс)
  validateOnBlur: true,    // Валидировать при потере фокуса
  validateOnInput: true,   // Валидировать при вводе
  validateOnSubmit: true,  // Валидировать при отправке
  rules: {
    // ... правила
  }
});

API методы

validateField(fieldName)

Валидирует конкретное поле вручную:

validator.validateField('email');

validateForm()

Валидирует всю форму и возвращает результат:

const isValid = validator.validateForm();
if (isValid) {
  console.log('Форма валидна!');
}

clearValidation()

Очищает всю валидацию (убирает подсветку и сообщения):

validator.clearValidation();

destroy()

Удаляет все обработчики событий:

validator.destroy();

Пример интеграции с формой регистрации

import { initLiveValidation } from './liveValidationHandler.js';

document.addEventListener('DOMContentLoaded', function () {
  const validator = initLiveValidation({
    formSelector: 'form',
    debounce: 500,
    rules: {
      email: [
        { type: 'required', message: 'Email обязателен' },
        { type: 'email', message: 'Введите корректный email' }
      ],
      password1: [
        { type: 'required', message: 'Пароль обязателен' },
        { type: 'minLength', value: 6, message: 'Минимум 6 символов' }
      ],
      password2: [
        { type: 'required', message: 'Подтвердите пароль' },
        { type: 'match', field: 'password1', message: 'Пароли не совпадают' }
      ]
    }
  });

  // Ревалидация password2 при изменении password1
  document.querySelector('[name="password1"]')?.addEventListener('input', () => {
    const password2 = document.querySelector('[name="password2"]');
    if (password2 && password2.value) {
      validator.validateField('password2');
    }
  });
});

Как это выглядит

До ввода

Поля обычные, без подсветки.

Во время ввода (после первого blur)

  • ✅ Зелёная рамка - поле валидно
  • ❌ Красная рамка - есть ошибка
  • 💬 Текст ошибки - красный текст под полем

При отправке формы

  • Все невалидные поля подсвечиваются красным
  • Форма не отправляется если есть ошибки
  • Фокус переходит на первое невалидное поле

Совместимость с Bootstrap

Модуль использует стандартные Bootstrap классы:

  • .is-valid - валидное поле
  • .is-invalid - невалидное поле
  • .invalid-feedback - контейнер для сообщения об ошибке

Производительность

  • Debounce предотвращает избыточные проверки при быстром вводе
  • Ленивая валидация - поля проверяются только после первого blur
  • Умная ревалидация - связанные поля (например, password2) обновляются автоматически

Примечания

  1. Валидация начинается после первого blur (потери фокуса) поля
  2. После blur валидация работает в реальном времени при каждом вводе
  3. Финальная валидация всегда происходит при submit формы
  4. Можно комбинировать несколько правил для одного поля
  5. Правила проверяются последовательно, первая ошибка останавливает проверку

Интеграция с AJAX формами

Если форма отправляется через AJAX, можно использовать метод validateForm() перед отправкой:

form.addEventListener('submit', async (e) => {
  e.preventDefault();
  
  if (!validator.validateForm()) {
    console.log('Форма содержит ошибки');
    return;
  }
  
  // Отправка через fetch
  const formData = new FormData(form);
  const response = await fetch('/api/register/', {
    method: 'POST',
    body: formData
  });
  
  // Обработка ответа...
});