geektimes

PrettyForms — простая клиент-серверная валидация форм

  • четверг, 20 ноября 2014 г. в 02:10:38
http://habrahabr.ru/post/243637/

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

Поэтому я и решил в конце-концов собрать весь код, который я писал в проектах, и скомпоновать его в одну небольшую библиотеку под названием PrettyForms. Библиотека эта содержит совсем немного кода, но при этом задачу свою она уже сейчас неплохо решает.

Зависимости: jQuery.

Пример работы:
image

PrettyForms изначально заточена под сайты, созданные на основе Twitter Bootstrap, но вы легко можете заменить её шаблоны с собщениями об ошибках на свои собственные, переопределив три переменных в объекте "PrettyForms.templates".

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

Самый простой вариант


Чтобы она просто начала работать, необходимо лишь подключить её к странице, а после этого добавить для всех полей, для которых необходима валидация, атрибут «data-validation», содержащий правила валидации, описанные на странице библиотеки в разделе «Валидаторы полей».

Всё. Больше ничего делать не надо, всё остальное библиотека сделает за вас :) К этому я и стремился изначально: как можно меньше телодвижений.

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

Вариант с клиент-серверной валидацией


Алгоритм работы:
  • Пользователь заполняет поля и нажимает кнопку отправки формы. Библиотека проводит валидацию всех данных, и если всё нормально, она собирает все данные формы, отправляет POST-запрос на сервер и ожидает от него JSON-ответ в специальном формате.
  • Сервер, получив запрос, проводит дополнительную валидацию данных уже на своей стороне. Если возникли ошибки при серверной валидации, он возвращает клиенту специальным образом сформированный JSON-ответ, содержащий команду для отображения ошибок серверной валидации с информацией о полях и содержащихся в них ошибках.
  • Если данные успешно прошли валидацию и на сервере, сервер производит необходимые операции и возвращает JSON-ответ с командами, описывающими действия, которые клиентская машина должна выполнить после успешного выполнения операции.


То есть, сервер всегда отвечает определённым набором команд для браузера, а браузер просто исполняет данные команды на клиенской машине. Таков алгоритм работы библиотеки. Более подробное описание протокола можно найти на странице библиотеки в разделе «Формат протокола общения клиента с сервером».

Для того чтобы настроить библиотеку для работы с сервером, добавьте к вашей стандартной кнопке отправки формы класс senddata, благодаря которому клики по кнопке будут перехвачены и обработаны библиотекой. Также ей следует добавить два новых атрибута:
  • data-input="<jquery-селектор формы, из которой будут собраны данные>"
  • data-link="<url, на который будут отправлены данные>"


Теперь библиотека не только будет производить клиентскую валидацию, но и станет отвечать за отправку данных на сервер и обработку ответа.

Пример формы для Bootstrap-фреймворка с атрибутами валидации:

<form class="form-horizontal" role="form" method="POST">
    <h1 class="form-signin-heading">Регистрация</h1>
    <div class="form-group">
        <label for="inputEmail3" class="col-sm-2 control-label">Email</label>
        <div class="col-sm-10">
            <input type="email"
                   class="form-control"
                   id="inputEmail3"
                   name="email"
                   data-validation="notempty;isemail"
                   placeholder="Введите ваш email">
        </div>
    </div>
    <div class="form-group">
        <label for="inputPassword3" class="col-sm-2 control-label">Пароль</label>
        <div class="col-sm-10">
            <input
                type="password"
                class="form-control"
                id="inputPassword3"
                name="password"
                data-validation="notempty;minlength:6"
                placeholder="Ваш пароль">
        </div>
    </div>
    <div class="form-group">
        <label for="inputPassword4" class="col-sm-2 control-label">Повторите пароль</label>
        <div class="col-sm-10">
            <input type="password"
                   class="form-control"
                   id="inputPassword4"
                   name="password_retry"
                   data-validation="notempty;passretry"
                   placeholder="Повторите пароль, вдруг ошиблись при вводе? Мы проверим это.">
        </div>
    </div>
    <div class="form-group">
        <div class="col-sm-offset-2 col-sm-10">
            <div type="submit"
                    data-input=".form-horizontal"
                    data-link="<?=URL::to('register')?>"
                    data-clearinputs="true"
                    class="btn btn-default senddata">Зарегистрироваться</div>
        </div>
    </div>
</form>



Теперь, кликая по кнопке «Зарегистрироваться», мы заставим библиотеку проверить данные формы на валидность, а после этого отправить их на сервер и обработать ответ.

Валидация на сервере


Валидацией на сервере должен заниматься тот фреймворк, с которым вы работаете. Библиотека лишь предоставляет класс, упрощающий создание корректного JSON-ответа с командами для клиента.

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

Чтобы включить валидацию для какого-либо контроллера и модели Laravel, подключите к нужной модели трейт для подключения функционала валидации, а также опишите в ней массив с правилами валидации для полей:
use PrettyForms\LaravelValidatorTrait;
class User extends Eloquent implements UserInterface, RemindableInterface {

    use UserTrait, RemindableTrait, LaravelValidatorTrait;

    //...

    private $rules = [
        'email'    => 'required|email|unique:users,email',
        'password' => 'required|min:6'
    ];

}


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

use PrettyForms\LaravelResponse;

    //...

    $user           = new User;
    $user->email    = Input::get('email');
    $user->password = Hash::make(Input::get('password'));
    $user->validateAndSave();

    // Ошибок валидации не произошло, генерируем ответ с одной командой: редирект пользователя
    return LaravelResponse::generate([
        'redirect' => '/login'
    ]);


Метод LaravelResponse::generate принимает ассоциативный массив из команд и их параметров, которые будут выполнены на клиенской машине. Изначально библиотека поддерживает лишь две команды: validation_errors и redirect. Первая команда используется библиотекой для отправки ошибок формы, вторая — для редиректа пользователя в другое место. Вы можете легко расширить функционал библиотеки, добавив свои собственные обработчики команд, посмотрев на примеры того, как это сделано в оригинальном коде библиотеки.

В общем-то, на этом — всё. Вот таким простым образом можно реализовать валидацию на клиенте и сервере без излишней головной боли, настройки гиганстких плагинов, написания кучи кода в контроллерах, и так далее) Надеюсь, эта библиотека поможет кому-то еще, и я не зря писал весь этот текст)

Проблемы


Библиотека не представляет из себя решение на все случаи жизни и не нацелена на подобное развитие. Это скорее небольшая заготовка, которую вы можете использовать и дорабатывать под свои нужды в своих собственных проектах.

В данный момент, одна из проблем — это невозможность собирать инпуты с теми типами, которые были описаны в стандартах HTML5, хотя их поддержку можно легко добавить в библиотеку, но в данный момент у меня просто не возникало данной необходимости.

Одна из частых проблем — это трудности с получением содержимого из тех полей, к которым применён какой-то дополнительный плагин, вроде Chosen или CKEDitor. Конкретно для двух этих плагинов в библиотеке уже встроена поддержка, и она корректно получает значения из полей, связанных с данными плагинами, но в мире существуют тысячи других плагинов, с которыми она может работать некорректно. Следует учитывать это при использовании библиотеки.