Валидация форм

Библиотека Cash предоставляет облегчённый интерфейс для работы с DOM, аналогичный jQuery, но с меньшим размером и высокой производительностью. В контексте валидации форм её возможности позволяют эффективно управлять событиями, изменениями полей и манипулировать классами элементов для отображения ошибок.


Выбор элементов формы

Выбор элементов формы в Cash осуществляется с помощью селекторов, аналогично CSS:

const form = $('#myForm');
const inputs = form.find('input, textarea, select');

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


Добавление обработчиков событий

Основным инструментом валидации является подписка на события. Наиболее распространённые события для проверки формы:

  • input — срабатывает при изменении значения поля.
  • blur — срабатывает при уходе фокуса с поля.
  • submit — событие формы при отправке.

Пример:

inputs.on('input', function() {
    const value = $(this).val();
    validateField($(this), value);
});

form.on('submit', function(e) {
    e.preventDefault();
    if (validateForm(inputs)) {
        this.submit();
    }
});

Метод val() используется для получения текущего значения поля, а метод on позволяет привязать функцию к событию.


Проверка полей

Валидация обычно строится на условных проверках значений. Основные типы проверки:

  • Проверка на пустоту:
function isEmpty(value) {
    return value.trim() === '';
}
  • Проверка по регулярному выражению:
function isEmail(value) {
    const regex = /^[\w.-]+@[\w.-]+\.\w+$/;
    return regex.test(value);
}
  • Проверка длины строки:
function isLengthValid(value, min, max) {
    return value.length >= min && value.length <= max;
}

Вывод ошибок

Для визуального отображения ошибок используется добавление или удаление классов к полям формы и вывод сообщений рядом с ними:

function showError(input, message) {
    input.addClass('error');
    let errorElement = input.siblings('.error-message');
    if (!errorElement.length) {
        errorElement = $('');
        input.after(errorElement);
    }
    errorElement.text(message);
}

function clearError(input) {
    input.removeClass('error');
    input.siblings('.error-message').remove();
}

Использование методов addClass, removeClass, siblings и after позволяет гибко управлять DOM и поддерживать чистоту структуры формы.


Общая проверка формы

Для проверки всех полей формы создаётся функция, которая перебирает элементы и применяет соответствующие проверки:

function validateForm(inputs) {
    let isValid = true;

    inputs.each(function() {
        const input = $(this);
        const value = input.val();

        clearError(input);

        if (isEmpty(value)) {
            showError(input, 'Поле не может быть пустым');
            isValid = false;
        } else if (input.attr('type') === 'email' && !isEmail(value)) {
            showError(input, 'Неверный формат email');
            isValid = false;
        } else if (input.attr('data-minlength')) {
            const min = parseInt(input.attr('data-minlength'), 10);
            if (!isLengthValid(value, min, Infinity)) {
                showError(input, `Минимальная длина ${min} символов`);
                isValid = false;
            }
        }
    });

    return isValid;
}

Метод each перебирает коллекцию элементов, а атрибуты attr позволяют задавать дополнительные правила валидации прямо в HTML.


Динамическая валидация по мере ввода

Для улучшения UX часто применяется валидация на лету, без ожидания отправки формы:

inputs.on('input', function() {
    const input = $(this);
    const value = input.val();

    clearError(input);

    if (isEmpty(value)) {
        showError(input, 'Поле не может быть пустым');
    } else if (input.attr('type') === 'email' && !isEmail(value)) {
        showError(input, 'Неверный формат email');
    }
});

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


Работа с чекбоксами и радиокнопками

Для checkbox и radio используется метод prop для получения состояния выбора:

const termsAccepted = $('#terms').prop('checked');

if (!termsAccepted) {
    showError($('#terms'), 'Необходимо согласие с условиями');
}

Метод prop возвращает логическое значение, что упрощает проверку булевых полей.


Асинхронная валидация

Иногда требуется проверка данных на сервере, например, уникальности email. Cash позволяет комбинировать асинхронные операции:

async function validateEmailUnique(input) {
    const value = input.val();
    try {
        const response = await fetch(`/check-email?email=${encodeURIComponent(value)}`);
        const data = await response.json();
        if (!data.available) {
            showError(input, 'Email уже зарегистрирован');
        }
    } catch (err) {
        showError(input, 'Ошибка проверки email');
    }
}

Объединение событий Cash и fetch позволяет делать эффективную и отзывчивую проверку формы.


Масштабирование валидации

Для больших форм рекомендуется строить массив правил валидации, где каждое правило содержит:

  • селектор поля,
  • функцию проверки,
  • сообщение об ошибке.

Пример структуры:

const rules = [
    { selector: '#username', test: value => !isEmpty(value), message: 'Введите имя' },
    { selector: '#email', test: value => isEmail(value), message: 'Неверный email' },
    { selector: '#password', test: value => isLengthValid(value, 6, 20), message: 'Длина пароля от 6 до 20' }
];

Функция проверки перебирает правила:

function validateWithRules(rules) {
    let isValid = true;
    rules.forEach(rule => {
        const input = $(rule.selector);
        clearError(input);
        if (!rule.test(input.val())) {
            showError(input, rule.message);
            isValid = false;
        }
    });
    return isValid;
}

Такой подход повышает читаемость и поддерживаемость кода при росте количества полей и правил.