问题
I am working on a proyect with MVC3 and I am trying to integrate qTip2 with jQuery validation in order to show errors as floating tips. The problem I am having is that apparently calling errorPlacement on form validation is not doing anything, guess it has something to do with the way MVC handles it.
Basically, what I want to do is use the integrated validation between MVC3 and jQuery (annotations) but also integrated with qTip to change how the error msg is shown.
I have searched all over and the best I could find was someone suggesting modifying the jquery.validate.unobtrusive.js - onError function, but I checked it out and had no idea how to modify it properly, plus would prefer a solution that did not require me to alter existing scripts.
Thank you for your help.
What I have so far:
My Model:
public class User
{
[Required]
public string Id { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
public string FirstName { get; set; }
public string SecondName { get; set; }
public string LastName { get; set; }
}
My javascript in my view:
$('#Form').validate({
errorClass: "errormessage",
errorClass: 'error',
validClass: 'valid',
errorPlacement: function (error, element) {
// Set positioning based on the elements position in the form
var elem = $(element),
corners = ['left center', 'right center'],
flipIt = elem.parents('span.right').length > 0;
// Check we have a valid error message
if (true) {
// Apply the tooltip only if it isn't valid
elem.filter(':not(.valid)').qtip({
overwrite: false,
content: error,
position: {
my: corners[flipIt ? 0 : 1],
at: corners[flipIt ? 1 : 0],
viewport: $(window)
},
show: {
event: false,
ready: true
},
hide: false,
style: {
classes: 'ui-tooltip-red' // Make it red... the classic error colour!
}
})
// If we have a tooltip on this element already, just update its content
.qtip('option', 'content.text', error);
}
// If the error is empty, remove the qTip
else { elem.qtip('destroy'); }
},
success: $.noop // Odd workaround for errorPlacement not firing!
})
$('#Form').submit(function () {
if (!$(this).valid())
return false;
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
beforeSend: function () {
},
success: function (result) {
},
error: function (result) {
}
});
return false;
});
回答1:
Great solution thanks, I've used this im my application.
...To further add, instead of modifying the jquery.validate.unobtrusive.min.js file directly I used the following to modify the default behaviour of unobtrusive validation.
$(document).ready(function () {
var settngs = $.data($('form')[0], 'validator').settings;
settngs.errorPlacement = function(error, inputElement) {
// Modify error placement here
};
});
Eagerly Performing ASP.NET MVC 3 Unobtrusive Client Side Validation
回答2:
Alternate Solution
My first solution worked, but also caused some unexpected behaivior in certain situation. I fixed by including the errorPlacement code on the onError function in the same js file:
function onError(error, inputElement) { // 'this' is the form element
var container = $(this).find("[data-valmsg-for='" + inputElement[0].name + "']"),
replace = $.parseJSON(container.attr("data-valmsg-replace")) !== false;
container.removeClass("field-validation-valid").addClass("field-validation-error");
error.data("unobtrusiveContainer", container);
if (replace) {
container.empty();
error.removeClass("input-validation-error").appendTo(container);
}
else {
error.hide();
}
var element = inputElement;
// Set positioning based on the elements position in the form
var elem = $(element),
corners = ['left center', 'right center'],
flipIt = elem.parents('span.right').length > 0;
// Check we have a valid error message
if (!error.is(':empty')) {
// Apply the tooltip only if it isn't valid
elem.filter(':not(.valid)').qtip({
overwrite: false,
content: error,
position: {
my: corners[flipIt ? 0 : 1],
at: corners[flipIt ? 1 : 0],
viewport: $(window)
},
show: {
event: false,
ready: true
},
hide: false,
style: {
classes: 'ui-tooltip-red' // Make it red... the classic error colour!
}
})
// If we have a tooltip on this element already, just update its content
.qtip('option', 'content.text', error);
}
// If the error is empty, remove the qTip
else { elem.qtip('destroy'); }
}
And then you can submit a form, checking for validation this way:
$('#frm').submit(function () {
if (!$(this).valid())
return false;
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
beforeSend: function () {
},
success: function (result) {
},
error: function (result) {
}
});
return false;
});
回答3:
My solution - can be used in separate .js file and if placed in master page, works for whole site.
$(document).ready(function () {
//validation - make sure this is included after jquery.validate.unobtrusive.js
//unobtrusive validate plugin overrides all defaults, so override them again
$('form').each(function () {
OverrideUnobtrusiveSettings(this);
});
//in case someone calls $.validator.unobtrusive.parse, override it also
var oldUnobtrusiveParse = $.validator.unobtrusive.parse;
$.validator.unobtrusive.parse = function (selector) {
oldUnobtrusiveParse(selector);
$('form').each(function () {
OverrideUnobtrusiveSettings(this);
});
};
//replace validation settings function
function OverrideUnobtrusiveSettings(formElement) {
var settngs = $.data(formElement, 'validator').settings;
//standard qTip2 stuff copied from sample
settngs.errorPlacement = function (error, element) {
// Set positioning based on the elements position in the form
var elem = $(element);
// Check we have a valid error message
if (!error.is(':empty')) {
// Apply the tooltip only if it isn't valid
elem.filter(':not(.valid)').qtip({
overwrite: false,
content: error,
position: {
my: 'center left', // Position my top left...
at: 'center right', // at the bottom right of...
viewport: $(window)
},
show: {
event: false,
ready: true
},
hide: false,
style: {
classes: 'qtip-red' // Make it red... the classic error colour!
}
})
// If we have a tooltip on this element already, just update its content
.qtip('option', 'content.text', error);
}
// If the error is empty, remove the qTip
else { elem.qtip('destroy'); }
};
settngs.success = $.noop;
}
});
回答4:
Found the answer... posting for reference.
1) First, locate the script jquery.validate.unobtrusive.js provided by microsoft.
2) Second, on the script locate the function validationInfo(form) and replace the errorPlacement instruction in the options structure with the one provided by qTip, or any of your choice.
3) Same goes for style and other options you wish to change in how validation is handled.
4) Include all necessary files were needed.
Hope this helps someone having a similar problem.
Example Code:
function validationInfo(form) {
var $form = $(form),
result = $form.data(data_validation);
if (!result) {
result = {
options: { // options structure passed to jQuery Validate's validate() method
//errorClass: "input-validation-error",
errorClass: "error",
errorElement: "span",
//errorPlacement: $.proxy(onError, form),
errorPlacement: function (onError, form) {
var error = onError;
var element = form;
// Set positioning based on the elements position in the form
var elem = $(element),
corners = ['left center', 'right center'],
flipIt = elem.parents('span.right').length > 0;
// Check we have a valid error message
if (!error.is(':empty')) {
// Apply the tooltip only if it isn't valid
elem.filter(':not(.valid)').qtip({
overwrite: false,
content: error,
position: {
my: corners[flipIt ? 0 : 1],
at: corners[flipIt ? 1 : 0],
viewport: $(window)
},
show: {
event: false,
ready: true
},
hide: false,
style: {
classes: 'ui-tooltip-red' // Make it red... the classic error colour!
}
})
// If we have a tooltip on this element already, just update its content
.qtip('option', 'content.text', error);
}
// If the error is empty, remove the qTip
else { elem.qtip('destroy'); }
},
invalidHandler: $.proxy(onErrors, form),
messages: {},
rules: {},
success: $.proxy(onSuccess, form)
},
attachValidation: function () {
$form.validate(this.options);
},
validate: function () { // a validation function that is called by unobtrusive Ajax
$form.validate();
return $form.valid();
}
};
$form.data(data_validation, result);
}
return result;
}
回答5:
With Mantisimo
& AJC
answers (thanks to him), I written the following script, it's OK and it works without any problems but jquery.validate.unobtrusive.js
throws an error as the following in each submitting form :
$(document).ready(function () {
var $forms = $.data($('form')[0], 'validator');
if ($forms == undefined) return;
var settngs = $forms.settings;
settngs.errorPlacement = function (error, inputElement) {
var element = inputElement;
var elem = $(element),
corners = ['left center', 'right center'],
flipIt = elem.parents('span.right').length > 0;
if (!error.is(':empty')) {
elem.filter(':not(.valid)').qtip({
overwrite: false,
content: error,
position: {
my: corners[flipIt ? 0 : 1],
at: corners[flipIt ? 1 : 0],
viewport: $(window)
},
show: {
event: false,
ready: true
},
hide: false,
style: {
classes: 'qtip-red',
}
})
.qtip('option', 'content.text', error);
}
else { elem.qtip('destroy'); }
};
});
I've tested with MVC 5 and qtip 2.2.0
来源:https://stackoverflow.com/questions/6802045/integrating-qtip-with-mvc3-and-jquery-validation-errorplacement