ASP.NET MVC Framework позволяет очень легко производить как серверную так и клиентскую валидацию «из коробки». Использование DataAnnotations в ваших моделях превращает процесс валидации в максимально простой алгоритм для разработчика. Фреймворк, в свою очередь, может отображать ошибки используя валидацию JQuery, или же в случае более комплексных ситуаций, ошибки могут быть возвращены уже после серверной валидации. Вот пример небольшой модели и соответствующих сообщений валидации в ошибочных полях.
В данном случае все поля модели являются обязательными, на что указывает атрибут «[Required]». Именно поэтому под каждым из полей отображается сообщение об ошибке. Просто замечательный функционал, но что же здесь не так? Для того чтобы более четко представить себе проблему и заодно узнать об еще одной «фишке» фреймворка попробуем ввести в поле «Price» любой нечисловой символ.
Не смотря на то, что мы не указывали никаких дополнительных атрибутов для нашей модели ASP.NET MVC понимает, что поле «Price» имеет числовой тип и потому опять отображает еще более длинное, не очень эстетичное сообщение об ошибке. К тому же чрезмерная его высота приводит к изменениям высоты формы. Это нас не устраивает, поскольку в нашем случае наличие множества таких сообщений, которые то появляются, то исчезают, приведет к скачкам высоты формы, а это негативно повлияет на общий вид страницы.
В попытке сделать эту форму более приятной для глаз, а также, чтобы избежать постоянных изменений ее размеров я собираюсь показать, как можно сигнализировать об ошибках валидации путем подсветки нужных полей цветом, а также выводить текст ошибок валидации с помощью JQuery плагина Tipsy.
Наша цель заключается в приведении предыдущей формы к следующему виду:
Начнем с Razor разметки нашей формы.
@model WebUI.ViewModels.LinkViewModel
@using (Html.BeginForm("AddLink", "Links", FormMethod.Post, new { enctype = "multipart/form-data", name = "AddLinkForm", @class = "add-link" }))
{
<h2>
<b>Add a new link</b><a href="#">(?)</a></h2>
<div class="right">
<div class="fields">
<div class="close-button" id="hide_form_link">✖</div>
<div id="cell">
<div class="text-field name-url">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model=>model.Name, null, new {style="display:none;"})
</div>
</div>
<div id="cell">
<div class="text-field for-file">
@Html.TextBoxFor(model => model.Link, new { @class = "file_1", @type = "file" })
@Html.ValidationMessageFor(model => model.Link, null, new { style = "display:none;" })
</div>
</div>
<div id="cell">
<div class="text-field price-url">
@Html.EditorFor(model => model.Price)
@Html.ValidationMessageFor(model => model.Price, null, new { style = "display:none;" })
</div>
</div>
</div>
<div class="button">
<span class="left-bg"></span><span class="right-bg">Add link </span>
<input type="submit" name="" />
</div>
</div>
<div class="clearFix">
</div>
}
Здесь всё стандартно, отмечу лишь несколько деталей:
- каждый input обернут в дополнительный блок
<div id="cell">
; - сообщения валидации скрываются при помощи атрибута
style = "display:none;"
.
Также есть у нас довольно простой CSS класс .error
, который только и всего лишь рисует рамочку вокруг нужных нам input-ов:
.error .text-field input {
border-color: #d2d9dc;
box-shadow: inset 2px 2px 6px #EBEBEB, 0 0 4px #ffd9d9, 0 0 0 5px #ffd9d9;
}
Этот CSS класс мы будем применять к блокам-оберткам полей, которые имеют ошибки валидации. Я намеренно не буду приводить все CSS стили, которые используются в примере, поскольку это не повлияет на суть примера, но займет много места.
Для отслеживания результатов валидации каждого поля воспользуемся плагином JQuery Validate Hooks. Приведенный ниже JavaScript код привязывает выполнение функции highlightElement
к событию валидации каждого элемента input:
$(function () {
// Validation
$('form').addTriggersToJqueryValidate().triggerElementValidationsOnFormValidation();
$('input').elementValidation(function (element) {
highlightElement(element);
});
});
В свою очередь функция highlightElement
определяет существование ошибок валидации и в случае их наличия применяет CSS класс .error
к блоку, оборачивающему input. В случае отсутствия ошибок – наоборот.
function highlightElement(input) {
var el = $(input);
if (el.hasClass('input-validation-error')) {
el.parents('div.cell, div#cell').addClass('error');
} else {
el.parents('div.cell, div#cell').removeClass('error');
}
}
Таким образом, вместо текстовых сообщений об ошибках мы получаем цветовую подсветку каждого поля. Но этого явно не достаточно, нужно указать пользователю причину возникновения ошибки в текстовом виде. Для этого воспользуемся JQuery плагином Tipsy, который поможет нам отображать текст ошибки при наведении курсора на подсвеченный элемент.
Просто привяжем Tipsy ко всем блокам, в которых находятся элементы формы.
$('form').find("div#cell").find('.text-field').tipsy({ gravity: 'n' });
Параметром «gravity: 'n'»
устанавливается положение подсказки внизу элемента.
Осталось сделать последний штрих, а именно указать какой текст нужно отобразить в подсказке. Для этого немного дополним функцию highlightElement
:
function highlightElement(input) {
var el = $(input);
if (el.hasClass('input-validation-error')) {
el.parents('div.cell, div#cell').addClass('error');
//Set Tipsy text
var fieldDiv = el.parents('div#cell').find('.text-field');
var text = fieldDiv.find('span.field-validation-error').find('span').text();
fieldDiv.attr("original-title", text.toString());
} else {
el.parents('div.cell, div#cell').removeClass('error');
//Remove Tipsy text
el.parents('div#cell').find('.text-field').removeAttr("original-title");
}
}
Теперь мы считываем сообщение об ошибке из элемента span.field-validation-error
который в случае ошибки генерируется автоматически при помощи хелпера
@Html.ValidationMessageFor
Вот и всё, путем простых действий мы адаптировали нашу форму для цветовой подсветки ошибок валидации, а также реализовали вывод сообщений валидации в виде всплывающих подсказок при наведении на соответствующий элемент.
Автор: sqrter