Проверка данных форм - jQuery Validation Plugin

Проверка данных форм это чрезвычайно важная процедура для повышения “юзабилити” при работе с формами. В первую очередь потому, что пользователь сразу же получает уведомление в том случае, если какие либо данные введены неверно. Сегодня я расскажу об очень полезном плагине для jQuery, который облегчает задачу проверки введенных данных до минимума. Это jQuery Validation Plugin. Вот некоторые его возможности:

  1. Способен проверять значения email, URL, числа, цифры, номера кредитных карт, минимальное и максимальное значения и др.
  2. Поддержка удаленной проверки используя AJAX.
  3. Автоматическое отображение сообщений об ошибках.

Итак, попробуем скрипт в действии. Допустим, нам необходимо создать простую форму для логина пользователя, в которой есть 3 поля - имя пользователя, пароль и checkbox “запомнить”.

<form name="myForm" id="myForm" action="" method="post" style="margin:20px">
	<label for="username">Имя пользователя </label><br/>
	<input type="text" name="username" value="" /><br/>
	<label for="password">Пароль</label><br/>
	<input type="password" name="password" value="" /><br/><br/>
	<label for="remember">Запомнить меня:</label>
	<input type="checkbox" name="remember" /><br/><br/>
	<input type="submit" name="" value="Submit" />
</form>

Для начала нам понадобится подключить библиотеку jQuery и плагин в страницу:

<script src="../lib/jquery.js" type="text/javascript"></script>
<script src="../lib/jquery.delegate.js" type="text/javascript"></script>
<script src="../jquery.validate.js" type="text/javascript"></script>

Теперь можно вызывать функцию jQuery.validate() которая инициализирует форму. В качестве атрибута в функцию нужно передать объект, содержащий правила (rules) и сообщения об ошибках (messages) для каждого проверяемого поля:

$().ready(function(){
	$("#myForm").validate({
		rules : {
			username : {required : true, minlength: 2},
			password : "required"
		},
		messages : {
			username : {
				required : "Введите ваше имя",
				minlength : "Введите не менее, чем 2 символа."
			},
			password : "Введите пароль"
		}
	});
});

Здесь все довольно таки просто. Селектор $(”#myForm”) получает указатель на форму, а функция validate() устанавливает правила для полей в соответствии с полученными данными. Объект rules содержит имя поля и список правил. Если правил несколько, то они должны быть объединены в отдельный объект. Так, для поля пароль просто указано правило “required”, т.е. обязательное поле, в то время как для поля username указан объект содержащий два правила - required и minlength (минимально допустимое количество символов). Структура объекта messages такая же, как и для rules, за исключением того, что вместо атрибутов правил указаны сообщения об ошибках.

Если при отправке формы обнаружены ошибки, то форма не отправляется, а высвечивается сообщение об ошибке в виде тэга <lable> с классом error. Также класс error присваивается элементу input, вызвавшему ошибку. Воспользуемся этим чтобы ярко выделить это поле:

label.error {
	color: red;
	font-style: italic;
}
input.error {
	border: 1px dotted #f00;
}

Таким образом, сообщения об ошибках будут выделены красным курсивом, а рамка поля, вызвавшего ошибку, будет выделена красной прерывистой линией.

Демо этого примера можно посмотреть здесь.

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

<input id="email" class="required email" maxlength="40" name="email" />

Еще один полезный атрибут это submitHandler, который позволяет устанавливать обработчик для события отправки формы. Очень удобно если вам, к примеру, нужно создать форму которая передает данные на сервер используя AJAX. Пример:

$("#form").validate({
	submitHandler: function(form) {
		jQuery(form).ajaxSubmit({
			target: "#result"
		});
	}
});

Теперь поговорим о том, как же пользоваться AJAX при проверке данных. К примеру, довольно распространенный пример, проверка доступности имени пользователя при регистрации. Допустим, у нас есть простейшая форма для регистрации:

<form name="myForm" id="myForm" action="" method="post" style="margin:20px">
	<label for="username">Имя пользователя</label>
<input type=”text” name=”username” value=”" />
<label for=”password”>Пароль</label>
<input type=”password” name=”password” value=”" /><br/><br/> <input type=”submit” name=”" value=”Регистрация” /> </form>

Назначим для формы уже известные по предыдущему примеру правила required и minlength, но кроме этого, для поля username добавим правило remote со значением “test.php”. Таким образом мы указываем файл, к которому будет обращаться плагин для проверки данных. В запросе будет передаваться имя поля и его значение, т.е. так: test.php?username=vasia. В ответ скрипт должен вернуть результат проверки, если это false (простое текстовое значение), то высвечивается сообщение об ошибке:

$().ready(function(){
	$("#myForm").validate({
		rules : {
			username : {required : true, minlength: 2, remote : "test.php"},
			password : "required"
		},
		messages : {
			username : {
				required : "Введите ваше имя",
				minlength : "Введите не менее, чем 2 символа.",
				remote : "Это имя пользователя занято, выберите другое"
			},
			password : "Введите пароль"
		}
	});
});

Демо этого примера доступен здесь.

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

jQuery.extend(jQuery.validator.messages, {
        required: "Это поле необходимо заполнить",
        remote: "Исправьте это поле чтобы продолжить",
        email: "Введите правильный email адрес.",
        url: "Введите верный URL.",
        date: "Введите правильную дату.",
        dateISO: "Введите правильную дату (ISO).",
        number: "Введите число.",
        digits: "Введите только цифры.",
        creditcard: "Введите правильный номер вашей кредитной карты.",
        equalTo: "Повторите ввод значения еще раз.",
        accept: "Пожалуйста, введите значение с правильным расширением.",
        maxlength: jQuery.format("Нельзя вводить более {0} символов."),
        minlength: jQuery.format("Должно быть не менее {0} символов."),
        rangelength: jQuery.format("Введите от {0} до {1} символов."),
        range: jQuery.format("Введите число от {0} до {1}."),
        max: jQuery.format("Введите число меньше или равное {0}."),
        min: jQuery.format("Введите число больше или равное {0}.")
});

Плагин можно скачать здесь. Также к нему имеется документация.

Обновлено: минимальные требования для плагина jQuery-1.2.2.

До встречи!

Добавить в закладки:

Комментарии на “Проверка данных форм - jQuery Validation Plugin”

  1. Владимир:

    Очень интересная статья.
    У меня возник вопрос о проверке имени пользователя. В вашем примере проверка выполняется после нажатия на кнопку “Регистрация”.
    Иногда удобнее чтобы эта проверка выполнялась при событии onchange в этом поле. Сделать это обычным способом (без библиотеки) несложно, достаточно написать обработчик. Но можно ли подключить эту функцию к библиотеке, т.е. чтобы при сабмите формы запрос отправлялся с данными из всех полей одному скрипту, а при обновлении поля с именем - другому (и только с данными из указанного поля)?

  2. admin:

    Это мое упущение. На самом деле скрипт так и работает. Т.е. при изменении текста отправляются данные поля username скрипту test.php, как указано в директиве remote, а при сабмите данные идут в другой скрипт. Проблема в том, что у меня на сервере был установлен jQuery-1.2.1, в то время как минимальные требования для плагина это версия 1.2.2.
    Спасибо вам за замечание. Уже исправлено.

  3. Serg:

    Неразобрался где взять файл delegate.js
    По указаному линку
    Скачал 1.2.1, потом обновил до 1.2.2, но такого файла в дистрибутиве нет

  4. admin:

    Этот плагин идет отдельно от дистрибутива:
    http://dev.jquery.com/browser/trunk/plugins/delegate/jquery.delegate.js?rev=4786

    его можно скопировать из моего демо примера:
    http://www.jstoolbox.com/js/jquery.delegate.js

  5. bromium:

    При использовании Validate натолкнулся на проблему, когда форма обрабатывается только после того, как ДВАЖДЫ нажимаешь на кнопку сабмит.
    может быть, проблема в том, что форму я генерю скриптом. стандартным вызовом validate (чере ойгукн document ready) форма не видится. Пришлось в onsubmit формы запихивать функцию, в которой используется validate и отправка через ajax
    Самое интересное, что такая бага замечена не только мной - в jquery group такая проблема тоже озвучивалась, но решения нет пока. а может, я что-то не так делаю?

  6. admin:

    Трудно ответить на ваш вопрос не видя код. Если проблема в $.ready() и динамическом создании формы, то почему бы не добавить вызов validate() сразу после того как вы сгенерировали и добавили форму в DOM?

  7. bromium:

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

  8. admin:

    ну так покажите код, посмотрим, или вышлите мне на email

  9. Бруно Понтекорво:

    Приветствую.
    Как вывести сообщение возле поля, если валидация прошла успешно? У меня remote проверяет email на сервере, если false то говорит что занято, а как что-то вывести если сервер возвращает true, мол все нормально?
    Спасибо.

  10. admin:

    @Бруно Понтекорво

    Нужно добавить функцию-обработчик success примерно так:
    rules : { … },

    messages : { … },

    success: function(label) {
    var msg = ‘ ’;
    if (label.attr(’for’) == ‘username’)
    var msg = ‘Имя не занято’;
    label.html(msg).addClass(”checked”);
    }

    В атрибуте for сообщения об ошибке всегда хранится имя поля. Я просто определяю, если это к примеру username, то значит сообщение ‘Имя не занято’. Ну и плюс к этому лейблу добавляю класс checked.
    Хороший демо есть тут: http://jquery.bassistance.de/validate/demo/milk/

  11. Евгений:

    Спасибо за статью, но появился вопрос.
    Как работать с массивом полей, т.е.: user[name], user[password] ?

  12. admin:

    @Евгений
    Такие поля нужно указывать следующим образом:
    rules: {
    “user[name]”: “required”,
    “user[password]”: “required”

    }

    Кавычки здесь обязательны!

  13. Олег:

    А как сделать проверку даты в селектах на правильность. Что бы нельзя было выбрать например 31 сентября 2008 года. (в сентябре только 30 дней)?

  14. admin:

    @Олег
    Увы, но такую проверку пока сделать невозможно :( . Разве что самому изменять функцию проверки правильности даты. Я только что посмотрел код, который реализует проверку для дат, оказывается там просто идет проверка по регулярным выражениям. Например, для функции dateISO() стоит проверка следующего выражения:
    /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/
    т.е. должен быть следующий формат даты: 2008-08-26, причем валидатор скажет что такая запись тоже верна: 2008-36-54, хотя это не так.
    Функция date() в свою очередь использует следующее выражение:
    !/Invalid|NaN/.test(new Date(value))
    … которое также не в состоянии определить “правильность” даты.
    Надеюсь в следующем релизе эту недоработку устранят.

  15. Dimonchik:

    Тоже проблема с динамическим созданием формы и валидацией. Форма создается одна, но при изменении одного селекта, меняется содержимое формы (добавляются/удаляются инпуты, селекты и др.) Так вот, под каждое состояние формы своя валидация, которая выполняется при изменении состоянии все того же селекта, но некоторые поля не меняются, а правила для них да. Получается что при изменении содержания формы новые (добавленные) поля принимают новые правила, а поля, которые не изменились - правила не переопределяют. Вопрос - как переопределить правила для старых полей? Может кто подскажет?

  16. Web разработка. Когда использовать JavaScript библиотеки для проверки форм:

    […] Validation Plugin, о нем, кстати, написана очень хорошая статья Проверка данных форм. Для prototype тоже есть несколько аналогичных библиотек: […]

  17. dios:

    помгите плиз. очень срочно надо!…
    у мна есть формочка, но мне надо валидировать только несколько из ее текстовых полей; каждому нужному мне полю я даю id с именем правила(rules) по которому надо проводить проверку; при загрузке страници плагин “хочет” что бы у каждого елемента формы был id, в чем и состоит суть проблеммы(и пока это так форма не отправит данные).
    Сообщение из firebug:input type=”text” size=”5″ name=”sf_code2″ value=”" has no id assigned.
    прописать id для каждого елемента формы в моей ситуации не позволительно.

  18. admin:

    @dios
    Никаких id не нужно ставить вообще. Не выдумывайте ничего лишнего. Делайте так как в примере:
    $().ready(function(){
    $(”#myForm”).validate({
    rules : {
    username : {required : true, minlength: 2},
    password : “required”
    },
    messages : {
    username : {
    required : “Введите ваше имя”,
    minlength : “Введите не менее, чем 2 символа.”
    },
    password : “Введите пароль”
    }
    });
    });
    Здесь, из всех полей формы будут проверяться только две. Это как раз то, что вам нужно. И в полях ничего лишнего не нужно:
    <input type=”text” name=”username” value=”" />

  19. dios:

    to admin:
    у меня параметр name уже используется и для каждого элемента поля он уникален, потому и не могу сделать так как Ви написали…а можна сделать так что бы правило по которому проходит валидация привязывалась к класу элемента(class=”mail”, mail:{required : true, email : true})? потому что когда так делаю, то валидатор не видит class=”mail” :(

  20. admin:

    @dios
    Извините, не могу понять смысл:
    > у меня параметр name уже используется и для каждого элемента поля он уникален
    Так параметр name и должен использоваться во всех полях, и для каждого элемента он должен быть уникальным.
    Что касается классов, то нужно в элемент добавить:
    class=”required email”
    Это значит, что поле обязательное и там должен быть email.
    Есть и еще один, более радикальный метод - в плагине имеются функции, например email(). Нужно получить ссылку на элемент и вызвать функцию rules:
    $(”#myinput”).rules(”add”, “email”);
    Я его в действии не пробовал, но в документации это описано.

  21. ober:

    Нестандартный вопрос.
    jQuery.validate() инициализирует правила и сообщения об ошибках после загрузки страницы по событию $().ready
    А как в таком случае можно изменить проинициализированные сообщения об ошибках? Например, что бы вставить в них значение из текстового поля, заполненного пользователем (в момент инициализации поле пустое)?

  22. pontiak:

    помогите плиз, нужно проверить одно лишь поле и в случае ошибки вывести сообщение. У меня сообщение выводится во всех случаях…

    скрипт валидации форм !!!

    $(’.valid’).ready(function () {
    var patt = /\D/;
    $(’.valid .required’).each(function () {
    var classArray = $(this).attr(’class’).split(’ ‘);
    $(classArray).each(function(i){
    if (classArray[i] == ‘number’ && !( patt.test($(this).val()) ))
    {
    alert(’not a number’);
    }
    });
    });
    });

    .error {
    border: 2px solid #f00;
    }

    число ли введено? 
    еще одно поле просто так 

  23. admin:

    @ober
    Да вопрос нестандартный, и сделать так как вы хотите очень проблематично. Мне кажется можно сделать так: добавить к кнопке submit класс “cancel” - это отменит валидацию формы, затем добавить к опциям обработчик submitHandler - в него будет передано управление при отправке формы. Затем, используя ф-ию setDefaults установить заново опции messages с новыми значениями сообщений, ну и в конце вызвать валидацию формы вручную.
    submitHandler :function(myForm){
    $.validator.setDefaults({messages : …. });
    this.form();
    }

  24. admin:

    @pontiak
    Вы используете функцию each, а значит ваша проверка на валидность будет выполнена для всех полей вне зависимости от результата проверки.
    Вместо each используйте обыкновенный цикл:
    for (var i=0; i < classArray; i++){
    if (/* если код не валидный */) {
    alert(’error’);
    break;
    }
    }

  25. ober:

    @admin
    нашёл простое и изящное решение при помощи jQuery.format
    вот часть кода инициализации:

    messages: {
    user_email: {remote: (”Е-mail {0} уже зарегистрирован. Напомнить пароль“)},
    terms: “Ytj,[jlbvj принять условия.”
    }

    Оказалось, что для текстового поля {0} есть его содержание (в отличие от max/min и range, где вместо {0} и {1} подставляются соотв ограничители). Несколько неожиданно, но удобно. и не надо мутить с cancel и submitHandler :)

  26. ober:

    упс! исправляюсь:

    messages: {
    user_email: {remote: jQuery.format(”Е-mail {0} уже зарегистрирован. <a href\=\”restore_pwd?email={0}\”>Напомнить пароль</a>“)},
    terms: “Необходимо принять условия.”
    }

    P.S. Не мешало бы добавить какой нить тег для кода ;)

Оставить комментарий