Reputation: 7856
I'm new to jQuery and struggling a bit in terms of customising the style of validation elements (ASP.NET MVC3 project). I know that I can change the CSS for field-validation-error
, input-validation-error
etc., but what I'd like to achieve is as follows (using jQuery 1.5.1 and jQuery UI 1.8.11):
For a label / input element combination I'd like to change the label colour when validation fails (now only the background colour of the input element changes to light red). Furthermore I'd like to show an error icon to the right of the input element (this works) with the error message as a tooltip (this doesn't work).
Furthermore I'd like the validation summary to show up as a custom styled tooltip when hovering over the submit button of the form (no idea how to get this done).
Generally, the validation of my form does work, but I want to change the style of the elements as described above. What I don't get is why the validate
function does not seem to fire (here I thought I could start with errorPlacement
etc.). My code is as follows:
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
$(document).ready( function()
{
$("form").validate({
debug: true,
errorPlacement: function(error, element)
{
error.insertBefore(element);
},
submitHandler: function()
{
alert("submit");
}
});
});
[...]
@using(Html.BeginForm())
{
[...]
<td>@Html.LabelFor(model => model.SomeField)</td>
<td>
@Html.EditorFor(model => model.SomeField)
@Html.ValidationMessagesFor(model => model.ValidFrom)
</td>
[...]
@Html.ValidationSummary(false);
<input id="btnSubmit" name="submit" type="submit" value="Send" />
}
Despite setting debug: true
and defining the alert
for the submitHandler I cannot see any (validation related) output on the web developer console in Firefox. Neither can I see the alert
message when clicking the submit button when the form is valid, it just gets posted to the server. I also tried explicitly setting the form id and accessing it in jQuery as:
$("#myForm")...
[...]
@using(Html.BeginForm("Action","Controler", FormMethod.Post, new { id = "myForm" }))
{
[...]
Unfortunately this doesn't change anything. How can I style my validation elements as described above? Why is the validate
function not firing?
Upvotes: 2
Views: 1024
Reputation: 1537
Try putting class to modify the default design of asp.net mvc
e.g. :
@Html.ValidationMessageFor(
model => model.Property1, string.Empty, new
{
@class = "new-style-error-validation"
}
)
Upvotes: 1
Reputation: 7856
This really took me a while and included several things that I had to do / find out about / fix. To start with, however, I updated to the latest versions of jQuery (1.9.2)
and jQuery UI (1.10.3)
at the time of writing.
First of all I kept wondering why all my attempts to change the behaviour of the validation logic as described in my question. It turned out that for ASP.NET MVC
you can't just use the "normal" jQuery examples you find on so many pages, you have to get a reference to the validator to begin with:
// #popupDialog and #Formular are the CSS ids of my modal dialog and form.
var validator = $("#popupDialog").find("#Formular").data("validator");
Next step was to overwrite the errorPlacement
with an empty function, otherwise the original validation styles always got activated:
validator.settings.errorPlacement = function () {
};
Now the easier part was to change the style of the elements before and after the actual input element by simply selecting parent / child elements originating from the actual input element:
validator.settings.highlight = function (element) {
$(element).parent().parent().find("label:first").addClass("error");
$(element).parent().parent().find("span.required").addClass("error");
$(element).parent().parent().find("input:first").addClass("errorImage");
$(element).parent().parent().find("select:first").addClass("errorImage");
var errorMessage = $(element).attr("data-val-required");
if (errorMessage) {
$(element).parent().parent().find("input:first").attr("custom-error-message", errorMessage);
$(element).parent().parent().find("select:first").attr("custom-error-message", errorMessage);
}
};
validator.settings.unhighlight = function (element) {
$(element).parent().parent().find("label:first").removeClass("error");
$(element).parent().parent().find("span.required").removeClass("error");
$(element).parent().parent().find("input:first").removeClass("errorImage");
$(element).parent().parent().find("select:first").removeClass("errorImage");
$(element).parent().parent().find("input:first").attr("custom-error-message", "");
$(element).parent().parent().find("select:first").attr("custom-error-message", "");
};
validator.settings.errorContainer = "#btnSubmit";
One thing to note about the above code lines is that I didn't use the title
attribute for the error message but custom-error-message
(or call it whatever you like). This was due to problems I had with invalid DropDownList
controls - I couldn't click the arrow and select an item from the list anymore as the control directly lost focus (this, btw. is also a problem I found out when manually setting title
via .attr(...
in jQuery and not via .prop(...
).
The CSS classes and styles used above can be anything you like, furthermore the elements you want to style can be changed according to your needs. There are probably easier and more stable ways for selecting the required elements, but basically the above solution works for me and should be sufficient to get you started if you have similar problems.
For the submit
button I decided to show a static text instead of a list of all invalid controls' error messages, but the approach used below should still help if you need to add dynamic text:
$(document).tooltip({
position:
{
my: "left bottom-15px",
at: "center top",
using: function (position, feedback) {
$(this).css(position);
$("<div>")
.addClass("arrow")
.addClass(feedback.vertical)
.addClass(feedback.horizontal)
.appendTo(this);
}
},
items: ".errorImage, input[type='submit']", // restrict to certain elements
content: function () {
var element = $(this);
if (element.is("[custom-error-message]")) {
return element.attr("custom-error-message");
}
else {
if ($("#Formular").valid()) {
return "";
}
else
{
return "<span class='error'>Input validation</span><br />Some informative text.";
}
}
}
});
If there are more questions please feel free to ask, I know from my own experience that it can be quite a nightmare to get this whole thing to work, even though in the end it doesn't look too difficult.
Upvotes: 0