将qTip与MVC3和jQuery验证(errorPlacement)集成

13
我正在使用MVC3开发项目,尝试将qTip2与jQuery验证集成,以便将错误显示为浮动提示。问题在于,似乎在表单验证中调用errorPlacement没有任何作用,我猜这与MVC处理方式有关。
基本上,我想要做的是使用MVC3和jQuery(注释)之间的集成验证,并与qTip集成,以更改错误消息的显示方式。
我已经搜索了所有内容,最好的结果是有人建议修改jquery.validate.unobtrusive.js - onError函数,但我查看了它,不知道如何正确修改它,而且更希望找到不需要修改现有脚本的解决方案。
谢谢您的帮助。
我目前所拥有的:
我的模型:
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; }
}

我在视图中的 JavaScript:

$('#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;
});
5个回答

13

非常好的解决方案,谢谢。我已经在我的应用程序中使用了这个。

此外,为了进一步添加功能,我使用了以下方法来修改不显眼验证(unobtrusive validation)的默认行为,而不是直接修改jquery.validate.unobtrusive.min.js文件。

$(document).ready(function () {

            var settngs = $.data($('form')[0], 'validator').settings;
            settngs.errorPlacement = function(error, inputElement) {
                // Modify error placement here
            };
});

ASP.NET MVC 3非侵入式客户端验证的及时执行


11

备选方案

我的第一个解决方案有效,但在某些情况下也会导致一些意外行为。我通过在同一js文件中的onError函数中包含errorPlacement代码来修复它:

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'); }
}

然后你可以提交一个表单,通过以下方式进行验证:

$('#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;
});

以上解决方案也解决了我提到的问题。谢谢! - Nick Olsen
有什么想法可以让服务器端验证消息在向服务器提交后显示提示? - Nick Olsen
@Nick-Olsen - qTip集成与jQuery客户端验证兼容...要实现服务器端验证,我想你必须根据具体情况进行编程。但我不确定是否有更好的方法。我认为这可能是一个独立的问题。发布它,以便您可以得到整个社区的帮助... - AJC
顺便说一下,我找到了解决方法。解决方案可以在这里找到:https://dev59.com/CVrUa4cB1Zd3GeqPhCMB - Nick Olsen
@Nick-Olsen - 很酷...我以后可能会用到它...谢谢。 - AJC
显示剩余2条评论

5

我的解决方案 - 可以放在独立的 .js 文件中,如果放置在主页面中,则适用于整个网站。

$(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;
    }
});

这个很好用,但是在我的MVC项目中似乎没有应用'qtip-red'类。我总是得到黄色的?你有什么想法为什么会这样? - Spafa9

2
我找到了答案...为了参考而发布。
1)首先,找到由Microsoft提供的脚本jquery.validate.unobtrusive.js
2)其次,在脚本中定位function validationInfo(form),并将选项结构中的errorPlacement指令替换为由qTip提供的指令或您选择的任何指令。
3)同样适用于您希望更改的验证处理方式中的样式和其他选项。
4)在所需位置包含所有必要的文件。
希望这可以帮助遇到类似问题的人。
示例代码:
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;
}

谢谢您上面的提示,但是在jquery.validate.unobtrusive.js文件中的更改使得即使存在错误,表单仍然会提交。您如何恢复默认行为,即当存在错误时,表单不会提交? - Nick Olsen
1
@ Nick-Olsen - 我个人偏好使用jQuery Ajax提交每个提交,因此在进行Ajax调用之前,我会显式验证表单,例如: 如果(!$(this).valid()) return false; 然而,请注意,在我首次发布这个解决方案后,我进行了改进,解决了一些与特定情景相关的问题...我会将其作为另一个答案添加,以便您查看。 - AJC

0

MantisimoAJC 的帮助下,我编写了以下脚本,它可以正常工作且没有任何问题,但是每次提交表单时,jquery.validate.unobtrusive.js 都会抛出以下错误:

$(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'); }
    };
});

jquery.validate.unobtrusive.js error

我已经测试了 MVC 5 和 qtip 2.2.0


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接