首页 > 解决方案 > focusout 上的验证消息移动按钮,它可以防止 onclick 事件

问题描述

我有一个 JQuery 验证,可以验证焦点输出的字段,并在出现错误时在该字段下显示一个标签。

当我第一次聚焦该字段并输入无效值并单击该字段下的按钮时,出现验证消息,由于focusout事件而显示错误消息并且按钮的单击事件没有触发。

当事件的relatedTarget 是我的按钮时,我尝试在focusout 事件上添加preventdefault 并且它有效,因为验证没有触发。但我认为这不是纠正这个问题的好方法,因为我必须阻止对我拥有的应用程序中的所有按钮或控件进行验证,所以验证似乎没用。

我可以改为在 keyup 上触发验证,因此当 focusout 触发时验证消息已经存在,但是当有一个验证验证字段是否为 10 个字符长时,例如,它会在用户事件输入之前显示错误消息完整的价值。

我可以将验证消息放在其他地方,这样它就不会移动我的按钮,但是该字段下的验证消息是我工作的规范。

在下面的示例中,我有以下情况,其中字段验证为 MaxLength(5) :

我的模型:

using System.ComponentModel.DataAnnotations;

namespace TestClickValdiation.Models
{
    public class TestValidation
    {
        [MaxLength(5)]
        public string Test { get; set; }
    }
}

查看开始:

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

布局 :

<!DOCTYPE html>
<html>
<head>

</head>
<body>
@RenderBody()
</body>
</html>

我的观点 :

@model TestClickValdiation.Models.TestValidation

<script src="~/Scripts/jquery-3.3.1.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>

@using (Html.BeginForm("Go", "Home", FormMethod.Post))
{
    <div>
        <div>
            @Html.EditorFor(x => x.Test, new { htmlAttributes = new { @class = "form-control" } })
        </div>
        <div>
            @Html.ValidationMessageFor(x => x.Test)
        </div>
    </div>
    <button type="submit" onclick="window.alert('hello');">Submit</button>
}

全球.asax:


using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace TestClickValdiation
{
    public class MvcApplication : HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }
}


我的控制器:

using System.Web.Mvc;
using TestClickValdiation.Models;

namespace TestClickValdiation.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            TestValidation test = new TestValidation();
            return View(test);
        }

        public ActionResult Go(TestValidation test)
        {
            return View("Index", test);
        }
    }
}

我想要的是在最后一种情况下显示验证消息并显示警报。所以以下步骤:

现在只显示字段下的消息。


我从我的 jQuery 导入中删除了 .min 以在其中调试并测试使用 focusout 和 maxlength 属性的位置。

focusout 事件在 jQuery.validate.js 中:

        onfocusout: function( element ) {
            if ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) {
                this.element( element );
            }
        },

之后调用元素并在其中调用检查函数,然后为每个规则调用验证方法(在这种情况下为 maxlength)

        check: function( element ) {
            element = this.validationTargetFor( this.clean( element ) );

            var rules = $( element ).rules(),
                rulesCount = $.map( rules, function( n, i ) {
                    return i;
                } ).length,
                dependencyMismatch = false,
                val = this.elementValue( element ),
                result, method, rule, normalizer;

            // Prioritize the local normalizer defined for this element over the global one
            // if the former exists, otherwise user the global one in case it exists.
            if ( typeof rules.normalizer === "function" ) {
                normalizer = rules.normalizer;
            } else if ( typeof this.settings.normalizer === "function" ) {
                normalizer = this.settings.normalizer;
            }

            // If normalizer is defined, then call it to retreive the changed value instead
            // of using the real one.
            // Note that `this` in the normalizer is `element`.
            if ( normalizer ) {
                val = normalizer.call( element, val );

                if ( typeof val !== "string" ) {
                    throw new TypeError( "The normalizer should return a string value." );
                }

                // Delete the normalizer from rules to avoid treating it as a pre-defined method.
                delete rules.normalizer;
            }

            for ( method in rules ) {
                rule = { method: method, parameters: rules[ method ] };
                try {
                    result = $.validator.methods[ method ].call( this, val, element, rule.parameters );
...

然后是maxlength验证方法

        // https://jqueryvalidation.org/maxlength-method/
        maxlength: function( value, element, param ) {
            var length = $.isArray( value ) ? value.length : this.getLength( value, element );
            return this.optional( element ) || length <= param;
        },

标签: jqueryasp.net-mvcvalidationuser-interface

解决方案


推荐阅读