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

Владимир | | Ajax, CodeIgniter, HTML, JavaScript.

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

В случае web приложений ситуация только усложняется.

На мой взгляд, существует три основных источника проблем:
1) ошибки пользователя (тут вряд ли можно что-то сделать);
2) необходимость проверять данные на стороне сервера;
3) необходимость сообщать посетителю об ошибках без перезагрузки страницы.

Кроме того, существуют два способа отправки данных формы:
1) обычный (с перезагрузкой страницы);
2) асинхронный (ajax запрос, без перезагрузки страницы).

Естественно, эта ситуация привела к возникновению JavaScript библиотек, специально предназначенных для проверки данных форм перед их отправкой.

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

Принцип их работы примерно одинаков. Создаете форму с правилами (обычно они указываются в атрибутах class полей формы), подключаете библиотеку, если нужно, пишите свои собственные правила.

И все. При отправке формы библиотека проверит введенные значения и если не найдет ошибок – выполнит запрос, в противном случае – вставит в форму сообщения об ошибках.

Теперь посмотрите на диаграммы отправки данных для обычного и ajax запросов.

Отправка обычного запроса (миниатюра) Отправка ajax запроса (миниатюра)

Как видите, все недостатки налицо. Самое главное – дублируется код проверки данных на стороне браузера и сервера, причем на 2-х разных языках.

К тому же, если все сделано правильно, посетитель никогда не увидит страницу с ошибками от сервера (отправляется при обычном запросе, если серверный скрипт нашел ошибку в данных). Все ошибки должна найти JavaScript библиотека и прервать отправку запроса.

Посмотрим, что можно сделать.

Убирать проверку на стороне сервера, мягко говоря, не безопасно.

А вот на клиентской стороне ситуация интереснее.

Если убрать проверку для обычного запроса, получим серьезное уменьшение скорости работы интерфейса (страница будет перезагружаться даже при неправильно заполненной форме).

А вот в случае ajax запроса перезагрузки страницы не происходит. Сервер отправляет только результат обработки запроса (либо описания ошибок).

Скорость обработки таких запросов достаточно высокая (если, конечно, не отправлять в качестве описания ошибок картинку или видеоролик 🙂 ). Да и во время загрузки можно какой-нибудь анимированный загрузчик показать.

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

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

Этот пример может быть легко изменен под форму с любым количеством полей (о том, как это сделать, чуть позже).

Серверная часть написана на PHP с использованием фреймворка CodeIgniter.

Клиентская – JavaScript с использованием библиотеки prototype (версия должна быть не ниже 1.6.0).

Рассмотрим контроллер (main.php).

Примечание. Для тех, кто не знаком с CodeIgniter, поясню. При обращении к сайту будет вызван один из методов контроллера (по-умолчанию, index()). Подробнее о взаимодействии компонентов фреймворка можно почитать здесь.

class Main extends Controller {
	function Main() {
		parent::Controller();
	}
	function index() {
		//загружаем необходимые библиотеки и страницу с формой
		$this->load->helper('form');
		$this->load->helper('url');
		$this->load->view('mainform');
	}
	/**
	 * Этот метод обрабатывает ajax запрос с данными формы
	 */
	function processform() {
		$this->load->library('validation');

		$rules['field1'] = "required";
		$rules['field2'] = "required|min_length[5]";

		$fields['field1'] = "Поле 1";
		$fields['field2'] = "Поле 2";

		$this->validation->set_rules($rules);
		$this->validation->set_fields($fields);
		$this->validation->set_error_delimiters('', '');

		$res = array();
		if ($this->validation->run()) {
			$res['status'] = "OK";
		}
		else {
			$res['status'] = "ERR";
			$res['errMessages']['field1'] = $this->validation->field1_error;
			$res['errMessages']['field2'] = $this->validation->field2_error;
		}

		echo json_encode($res);
	}
}

Как видите, контроллер содержит два метода:
1) index() – загружает библиотеки и представление, создающее страницу с формой;
2) processform() – обрабатывает ajax запрос. Этот метод содержит обычный код проверки формы.
Сначала загружается библиотека validation (строка 15). Затем, устанавливаются правила и описания для каждого поля формы (строки 17-24). Обратите внимание, ключи элементов массива должны совпадать с id полей формы.

В строке 25 мы указываем, что строки с описанием ошибок не должны содержать html разметки (по-умолчанию, библиотека вставляет теги <p>).

После этого выполняем проверку (строка 28).

В зависимости от результатов проверки формируем массив, в котором в обязательном порядке должны быть элементы:
1) status – результат проверки (может быть OK или ERR);
2) errMessages – создается если status == 'ERR'. Этот параметр содержит массив с описаниями ошибок. Ключи массива должны совпадать с именами полей формы (нужно для автоматической обработки массива на стороне браузера).

После того, как массив сформирован, преобразуем его в формат JSON и отправляем браузеру.

Теперь рассмотрим представление, создающее форму (mainform.php).

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ru">
<head>
<title>Проверка данных форм</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<script type="text/javascript" src="<?php echo base_url(); ?>prototype.js"></script>
<script type="text/javascript" src="<?php echo base_url(); ?>script.js"></script>
<link rel="stylesheet" type="text/css" href="styles.css" />
</head>

<body>
<?php echo form_open('#'); ?>
<p>
<label for="field1">Поле 1: </label>
<input type="text" name="field1" id="field1" size="15" />
</p>
<p>
<label for="field2">Поле 2: </label>
<input type="text" name="field2" id="field2" size="15" />
</p>
<p>
<input type="button" value="Отправить" onclick="sendData('<?php echo site_url()."/main/processform"; ?>')" />
</p>
<?php echo form_close(); ?>
</body>
</html>

Разметка страницы тут принципиальной роли не играет. Главное, подключить необходимые библиотеки (строки 6 и 7) и правильно указать адрес обработчика запроса в параметре функции sendData (строка 22).

И, наконец, переходим к функции sendData (находится в файле script.js).

var fields = ["field1", "field2"];

function sendData(scriptUrl) {
	//читаем данные из формы
	//формируем строку с параметрами запроса
	var pars = $H();
	for (var i = 0; i < fields.length; i++) {
		pars.set(fields[i], $(fields[i]).value);
	}
	//отправляем ajax запрос
	new Ajax.Request(scriptUrl,
	{
		method:"post",
		parameters:pars.toQueryString(),
		onSuccess: function(transport) {
			var response = eval('(' + transport.responseText + ')');
			//удаляем старые сообщения об ошибках
			var errMess = $$('.error');
			errMess.each(
				function(el) {
					el.remove();
				}
			);
			if (response.status == "OK") {
				//код, который выполняется если форма заполнена правильно
				alert("ОК");
			}
			else {
				//выводим сообщения об ошибках
				var messages = response.errMessages;
				for (var i = 0; i < fields.length; i++) {
					var curField = fields[i];
					if (messages[curField] != null && messages[curField] != "") {
						new Insertion.After(curField,
							"<span class=\"error\">" + messages[curField] + "</span>");
					}
				}
			}
		},
		onFailure: function() {
			alert("При отправке запроса возникла ошибка");
		}
	});
}

Здесь выполняется чтение значений, введенных в форму (строки 6-9), отправка запроса (строка 11) и обработка его результатов (строки 15-39).

Если форма заполнена правильно, функция покажет сообщение со словом «ОК» (строка 26). Естественно, в реальной ситуации этот код нужно изменить.

А в случае возникновения ошибок – после каждого поля, содержащего неправильные значения, будет вставлена строка с описанием ошибки. Каждая такая строка находится между тегами <span class=”error”>...</span>, т.е. с помощью таблицы стилей эти ошибки легко выделить.

Обратите внимание. Функция sendData работает с любым количеством полей в форме. Нужно только добавить id этих полей в массив fields (строка 1).

Этот пример написан так, чтобы поддерживать формы с любым количеством полей. Для этого, нужно:

1) Изменить html разметку (добавить новые поля в форму), каждое поле должно иметь уникальный id.
2) добавить id полей в массив fields файл (script.js).
3) в методе processform() контроллера создаем правила для каждого поля и в массив $res['errMessages'] добавляем элементы, в которых будут храниться описания ошибок.

Вот и все. Главное – не ошибиться с id полей формы.

В качестве дополнения, приведу таблицу стилей (styles.css) для этой формы.

@CHARSET "UTF-8";

form {
	font-family: Verdana, sans-serif;
	font-size: 90%;
}
form p {
	clear: both;
}
form label {
	float: left;
	width: 20%;
}
.error {
	margin-left: 10px;
	color: #ff0000;
	font-size: 90%;
}

До встеречи!

P.S. А каким образом вы решаете проблемы с проверкой данных?