【问题标题】:How to set $jQval.unobtrusive.options ErrorPlacement function correclty如何正确设置 $jAva.unobtrusive.options ErrorPlacement 功能
【发布时间】:2014-08-18 02:51:31
【问题描述】:

在 jquery.validate.unobtrusive 中覆盖 ErrorPlacement 函数的正确方法是什么?

查看 jquery.validate.unobtrusive.js 脚本,开发人员的意图似乎是允许您通过设置 $jQval.unobtrusive.options 来应用自己的 ErrorPlacement 函数。

在定义errorPlacement函数的validationInfo(form)函数中,我们看到了对execInContext("errorPlacement", arguments)的调用。

似乎如果我们在 $.validator.unobtrusive.options 下创建一个 errorPlacement 函数,那么它就会被调用。

   $.validator.unobtrusive.options = {
        errorPlacement: function () {
            console.log("hello");
        }
    };

问题是这必须在 jquery.validate.js 之后和 jquery.validate.unobtrusive.js 被引用之前配置。否则 $jQval.unobtrusive.options 为 null 并且 $form.data(data_validation, result) 将不会被再次设置。

    function validationInfo(form) {
    var $form = $(form),
        result = $form.data(data_validation),
        onResetProxy = $.proxy(onReset, form),
        defaultOptions = $jQval.unobtrusive.options || {},
        execInContext = function (name, args) {
            var func = defaultOptions[name];
            func && $.isFunction(func) && func.apply(form, args);
        }

    if (!result) {
        result = {
            options: {  // options structure passed to jQuery Validate's validate() method
                errorClass: defaultOptions.errorClass || "input-validation-error",
                errorElement: defaultOptions.errorElement || "span",
                errorPlacement: function () {
                    onError.apply(form, arguments);
                    execInContext("errorPlacement", arguments);
                },
                invalidHandler: function () {
                    onErrors.apply(form, arguments);
                    execInContext("invalidHandler", arguments);
                },
                messages: {},
                rules: {},
                success: function () {
                    onSuccess.apply(form, arguments);
                    execInContext("success", arguments);
                }
            },
            attachValidation: function () {
                $form
                    .off("reset." + data_validation, onResetProxy)
                    .on("reset." + data_validation, onResetProxy)
                    .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;
}

解决这个问题的另一种方法是

  1. 设置$.validator.unobtrusive.options错误放置函数

  2. 移除不显眼的验证

  3. 重新应用不显眼的验证

    $.validator.unobtrusive.options = {
        errorPlacement: function () {
            console.log("errorPlacement");
        }
    };
    
    
    $("#form_selector").removeData("unobtrusiveValidation");
    
    // reapply the form's validator
    $.validator.unobtrusive.parse(document);
    

或者另一种选择是覆盖函数调用。

var validator = $("#form_selector").data('validator');
var originalFunction = validator.settings.errorPlacement;
validator.settings.errorPlacement = function(error,element) {
    console.log("errorPlacement");
    originalFunction(error, element);
};

哪种是实现您自己的 errorPlacement 方法的正确方法?

【问题讨论】:

  • 不认为你已经解决了这个问题(甚至还记得)?
  • 我现在不记得了。在我的帖子结束时,我建议了两种解决问题的方法。我想我可能已经完成了函数调用的覆盖。我觉得它更干净。

标签: jquery unobtrusive-validation


【解决方案1】:

迟到 3 年才回答,但事实证明我今天正是需要这个。在那个时间范围内可能已经修复了不显眼的代码,但是您的示例代码对我来说工作得很好。我将此添加到我在 jquery.validate.js 和 jquery.validate.unobtrusive.js 之后加载的站点脚本之一:

$.validator.unobtrusive.options = {
    errorPlacement: function () {
        console.log("hello");
    }
};

它运行良好,但有一个额外的问题:必须在文档准备好之前运行此行。 validationInfo 方法是通过这个在文档就绪时调用的,从jquery.validate.unobtrusive.js 的底部开始:

$(function () {
    $jQval.unobtrusive.parse(document);
}); 

parse 最终调用validationInfo。不显眼的代码的问题是validationInfo 设置defaultOptions = $jQval.unobtrusive.options || {}。显然,如果此时您还没有定义 unobtrusive.options,它会愚蠢地将defaultOptions 设置为一个空白对象,并且不再检查它,无论您对 $jQval.unobtrusive.options 做什么。如果他们只是删除了|| {},一切都会很好,因为它只是一个对象引用。唉……


如果您无法在加载文档之前设置 errorPlacement 回调,或者您需要动态更改它,只需在 jquery.validate.jsjquery.validate.unobtrusive.js 之后加载的脚本之一中添加这一行:

$.validator.unobtrusive.options = {};

这将导致defaultOptions 指向您可以引用的对象。然后,在您需要的任何地方,按照您的期望更改$.validator.unobtrusive.options。请注意不要覆盖该对象,因为如果这样做,您不会影响defaultOptions 指向的对象。即,这样做:

$.validator.unobtrusive.options.errorPlacement: function () {
    console.log("hello");
};

【讨论】:

  • 对我来说解决方案是*.com/questions/5487139/…
  • 你也可以在 jQuery document.ready 回调中设置不显眼的选项,该回调在代码中定义before引入不显眼的验证JS,我认为这是最优雅的解决方案。这保证了您的 document.ready 回调将在非侵入式验证的 document.ready 回调(它读取选项)之前运行,但它仍将在 $.validator.unobtrusive.options 由非侵入式验证 JS 定义之后运行。
【解决方案2】:

使用 Object.assign

经过一些实验,我能够使用下面的代码(在所有内容之后加载)让它工作。我正在使用基于引导程序的主题,因此它希望表单组容器上有错误

Object.assign($.validator.unobtrusive,
    {
        options: {
            errorPlacement: function(error, element) {
                const container = $(element).closest(".form-group, .form-group-custom");
                if (container.length) {
                    container.addClass("has-error");
                }
            },
            success: function(error, element) {
                const container = $(element).closest(".form-group, .form-group-custom");
                if (container.length) {
                    container.removeClass("has-error");
                }
            }
        }
    });

【讨论】:

    【解决方案3】:

    我在这个问题上苦苦挣扎了好几天,我尝试了几乎所有可能的选择。它在少数情况下有效,但并不可靠。应该满足的条件太多了。

    对我有用的是将“jquery.validate.unobtrusive.min.js”与我的脚本捆绑在一起。这每次都有效,无一例外。捆绑的顺序可能很重要,把你的脚本放在第二位。

    script.js:

    var settings = {
        errorPlacement: function errorPlacement(error, element) {
            console.log("hello");
        }
    }
    $.validator.unobtrusive.options = settings;
    

    bundleconfig.json(用于.NET环境。根据需要修改)

    [
      {
        "outputFileName": "wwwroot/js/jquery.validate.unobtrusive.custom.min.js",
        "inputFiles": [
          "wwwroot/lib/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.min.js",
          "wwwroot/js/script.js"
        ],
        "minify": {
          "enabled": true,
          "renameLocals": true
        },
        "sourceMap": false
      }
    ]
    

    【讨论】: