Introduction
When using JQuery unobtrusive validation, the error message is shown by creating a span
which displaces the position of the existing controls. If you have, for example, a horizontal form on top of other controls, then this behavior might not be working for you since it will break the page layout. It was the case for me and as such, I decided to change the default behavior of the JQuery unobtrusive validation library and instead of using a span
to show the error message, I decided to use a tooltip. I was also using Twitter Bootstrap so integrating with it was the next step.
Background
I started looking for a library which is doing that, but while there are libraries which do something similar, I haven’t found one doing exactly what I wanted. My starting point was the nugget package library with id jquery.validate.unobtrusive.bootstrap
which is an extension of jQuery Validate Unobtrusive for Bootstrap 3. There are a few articles describing how to show a Bootstrap tooltip as the validation message, but I have found none which also changes the style of the tooltip to something more appropriate for an error message. So I decided to write one of my own - jquery.validate.unobtrusive.bootstrap.tooltip.js.
Using the Code
Besides adding this library as a reference, you also have to add jQuery, jQuery validate and jQuery unobtrusive validation. I have registered the following script bundle:
bundles.Add(new ScriptBundle("~/bundles/validate").Include(
"~/Scripts/jquery.validate.js",
"~/Scripts/jquery.validate.unobtrusive.js",
"~/Scripts/own/jquery.validate.unobtrusive.bootstrap.tooltip.js"));
The page must also include bootstrap.css and boostrap.js. In addition, a stylesheet containing the tooltip customization classes which are included later on in this article has to be referenced.
The first required step was to change the showErrors
function. This is the last method on the validator before the methods which create the span
are called. It is done on the document load:
$(function () {
$('form').each(function () {
var validator = $(this).data('validator');
validator.settings.showErrors = onValidated;
});
});
The onValidated
function is iterating through all the controls with errors and it shows the error message as a tooltip. In the case a control is no longer in error state, it is added to success collection. The method iterates over the controls with no errors and it destroys the tooltips for them, as it can be seen below. The listing contains the whole JavaScript library:
(function ($) {
var classes = { groupIdentifier: ".form-group",
error: 'has-error', success: null };
function updateClasses(inputElement, toAdd, toRemove) {
var group = inputElement.closest(classes.groupIdentifier);
if (group.length > 0) {
group.addClass(toAdd).removeClass(toRemove);
}
}
function onError(inputElement, message) {
updateClasses(inputElement, classes.error, classes.success);
var options = { html: true, title:
'<div class="tooltip-alert alert-danger">' + message + '</div>' };
inputElement.tooltip("destroy")
.addClass("error")
.tooltip(options);
}
function onSuccess(inputElement) {
updateClasses(inputElement, classes.success, classes.error);
inputElement.tooltip("destroy");
}
function onValidated(errorMap, errorList) {
$.each(errorList, function () {
onError($(this.element), this.message);
});
if (this.settings.success) {
$.each(this.successList, function () {
onSuccess($(this));
});
}
}
$(function () {
$('form').each(function () {
var validator = $(this).data('validator');
validator.settings.showErrors = onValidated;
});
});
}(jQuery));
While initially I considered setting the form-group
as successfully validated, I decided that the normal appearance is more appropriate. If one wants to show it as successfully validated, though, this can be done by assigning to the success
class the has-success
bootstrap class.
To make the tooltip look appropriate as an error validation message, I had to make the content of the tooltip HTML and to include in it a div
with class class="tooltip-alert alert-danger"
containing the error message. The classes added to change the tooltip look are:
.tooltip-inner {
max-width: 300px;
padding: 0;
}
.tooltip-alert{
padding: 8px 10px;
font-weight: bolder;
color: #A94442;
}
The ASP.NET MVC view has a form which contains no validation message:
<form class="form-horizontal" role="form" onsubmit="return false;">
<div class="form-group col-sm-3">
@Html.LabelFor(model => model.From, new { @class = "control-label col-sm-2" })
<div class="col-sm-10">
@Html.TextBoxFor(m => m.From, new { type = "date", @class = "form-control" })
</div>
</div>
<div class="form-group col-sm-3">
@Html.LabelFor(model => model.To, new { @class = "control-label col-sm-1" })
<div class="col-sm-10">
@Html.TextBoxFor(m => m.To, new { type = "date", @class = "form-control" })
</div>
</div>
<div class="form-group col-sm-5">
@Html.LabelFor(model => model.Accounts, new { @class = "control-label col-sm-3" })
<div class="col-sm-9">
@Html.DropDownList("Accounts", Model.Accounts, new { @class = "form-control" })
</div>
</div>
<div class="col-sm-1">
<button type="submit" class="btn btn-default">Show</button>
</div>
</form>
The end result is the one from the image below:
Points of Interest
The interesting part of this code was not changing the jQuery unobtrusive validation library itself but extending it. Having a background in C# and server side development, this proved to be more easy to do than I was expecting.
History
- 6th April, 2014: Initial version