- Добавлены ManyToMany поля: departments, recipients, cc_users, sent_to_all_department - Старое поле department сохранено для обратной совместимости - Создана миграция с автоматическим переносом данных - Обновлены сериализаторы RequestReadSerializer и RequestWriteSerializer - Добавлен RecipientIDsField для поддержки разных форматов - Добавлены методы is_recipient, add_recipient, remove_recipient в модель - Добавлена валидация получателей и отделов
8.4 KiB
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) обновляются автоматически
Примечания
- Валидация начинается после первого blur (потери фокуса) поля
- После blur валидация работает в реальном времени при каждом вводе
- Финальная валидация всегда происходит при submit формы
- Можно комбинировать несколько правил для одного поля
- Правила проверяются последовательно, первая ошибка останавливает проверку
Интеграция с 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
});
// Обработка ответа...
});