zoukankan      html  css  js  c++  java
  • MVC与Validate验证提示的样式修改

      

      MVC中使用Validate的验证,要修改错误提示样式一共有3处需要修改,否则就不太完美了;

      MVC中的Validate的验证机制只用在后台写一次,就可以完成前台和后台的完美验证,前台的验证主要是依靠Validate.js来完成,Validate只是作为一个验证插件,但是错误提示是靠微软的jquery.validate.unobtrusive.js这个js来完成,但是他只负责给错误的边框加上红色,且在后面出现一个span来显示,有时候会撑坏布局;

      可以使用自定义的验证提示来做到比原始验证漂亮的验证提示;

      先是找到一款tip提示的插件,有事件和方法进行tip提示的代码控制显示和隐藏及销毁即可;poshytip:http://vadikom.com/demos/poshytip/# 还算不错,基本可以满足要求;

      MVC的强类型提交表单处理好之后:

    复制代码
    public class MemberUser
        {
            [Required(ErrorMessage="用户名不能为空")]
            public string UserName { get; set; }
            [Required(ErrorMessage = "密码不能为空")]
            public string PassWord { get; set; }
        }
    复制代码

      

         页面代码:

    复制代码
    @using (Ajax.BeginForm(new AjaxOptions { Url = "/Home/SaveMemberUser/" }))
        {
            @Html.ValidationSummary(true)
            <table>
                <tr>
                    <td style="80px;text-align:right;">用户</td>
                    <td style="200px">
                        @Html.TextBoxFor(m => m.UserName)
                        @Html.ValidationMessageFor(m=>m.UserName)
                    </td>
                </tr>
                <tr>
                    <td style=" 80px; text-align: right;">密码</td>
                    <td style="200px">
                        @Html.TextBoxFor(m => m.PassWord)
                        @Html.ValidationMessageFor(m => m.PassWord)
                    </td>
                </tr>
                <tr>
                    <td colspan="2" style="text-align:center">
                        <input type="submit" value="提交" />
                    </td>
                </tr>
            </table>
        }
    复制代码

      注:ValidationMessageFor是必须得,因为错误提示的跟踪点是在ValidationMessageFor生成的span上进行的;jquery、validate、validate. Unobtrusive这几个js是必须得;

      我们只需要将validate.unobtrusive中进行错误消息提示时进行拦截即可;每次错误提示都会触发validate.unobtrusive中的onError事件;我们改写如下就可以:

    复制代码
    function onError(error, inputElement) {  // 'this' is the form element
            var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"),
                replaceAttrValue = container.attr("data-valmsg-replace"),
                replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null;
            //add
            var $customErrorTip = container.attr("data-forerrortip");
            container.removeClass("field-validation-valid").addClass("field-validation-error");
            error.data("unobtrusiveContainer", container);
            //add
            var elem = $("#" + inputElement[0].name.replace(".", "_"));//添加提示消息
            if (replace) {
                container.empty();
                //add start
                if (error.html() != "") {
                    if ($customErrorTip) {
                        $("#" + $customErrorTip).poshytip("destroy");
                    } else {
                        elem.poshytip("destroy");
                    }
                    var direction = "right";
                    //左边+元素宽+提示的文字+提示两边的空白
                    if ((elem[0].offsetLeft + elem.width() + error.length * 10 + 20) > $(document).width()) {
                        direction = "left";
                    }
                    var errorConfig = {
                        content: error,
                        alignTo: 'target',
                        alignX: direction,
                        alignY: 'center',
                        showOn: 'none',
                        bgImageFrameSize: 7,
                        offsetX: 5
                    };
                    if ($customErrorTip) {
                        $("#" + $customErrorTip).poshytip(errorConfig).poshytip('show');
                    } else {
                        elem.filter(':not(.valid)').poshytip(errorConfig).poshytip('show');
                    }
                } else {
                    if ($customErrorTip) {
                        $("#" + $customErrorTip).poshytip("destroy");
                    } else {
                        elem.poshytip("destroy");
                    }
                }
                //add end
                //update disable
                //error.removeClass("input-validation-error").appendTo(container);
            }
            else {
                error.hide();
            }
        }
    复制代码

      效果图:

      到此就完了吗?在此错误提示,在鼠标离开或切换的时候,切实可以进行相应的错误提示;

      现在需求变了,如果是很多单选按钮组,需要至少选中一个怎么办了?如果不作任何修改,默认会在第一个按钮上tip提示为必填项,显然不能100%表达我们的意思;在上面的onError的js中,我判断了data-forerrortip这个属性,用法如下:

    <span id="groupRadioError" style="vertical-align:middle;line-height:70px;">&nbsp;</span>
            @Html.ValidationMessageFor(m => m.Option, "", new{data_forErrorTip="groupRadioError" })

      我定义一个空的span位置定义为自定义的位置,然后在ValidationMessageFor的时候加入一个自定义属性,指向我加入的空span的id,[有点label-for的意思],然后对比我们上面写的onError的js比较,意思就是错误的指向不是错误本身的元素对象而是data-forerrortip属性指向的id的元素进行错误提示

      到目前为止,你任务提示完了吗?这只是进行了一半了,MVC是前台和后台可以同时验证的,现在说的都只是前台进行的验证,如果后台验证有错误咋办?仔细观察几遍,如果后台有错误,在Response的时候,是直接把错误放在span中给显示出来的;现在可以将validate、validate.unobtrusive注释掉,并且不采用ajax提交,注释掉ajax提交的js[jquery.unobtrusive-ajax],表单改为

    @using (Ajax.BeginForm("SaveMemberUser", new { id = "Add" }, new AjaxOptions { Url = "/Home/SaveMemberUser/" }))
    {
    }

      如此这般,空表单直接提交,就完全没看到tip的提示效果,因为有tip的提示已经被我们注释掉了;刚说到,span的错误是直接Response出来的

      这样我们可以在页面刚加载完后就去找class为field-validation-error的样式进行each就可以了:

    复制代码
    $(function () {
        $(".field-validation-error").each(function () {
            var $this = $(this);
            var thisid = $this.attr("data-valmsg-for").replace(".", "_");
            var direction = "right";
            // 左边+元素宽+提示的文字+提示两边的空白
            if (($this[0].offsetLeft + $this.width() + $this.text().length * 10 + 20) > $(document).width()) {
                direction = "left";
            }
            $this.hide();
     
            setTimeout(function () {
                $("#" + thisid).poshytip({
                    content: $this.text(),
                    alignTo: 'target',
                    alignX: direction,
                    alignY: 'center',
                    showOn: 'none',
                    offsetX: 5
                }).poshytip('show');
            }, 100);
            
        });
    });
    复制代码

      使用setTimeout来控制显示的原因,是因为在使用$();加载的时候,元素已经加载了,但元素的位置信息还未完成初始化,所以tip的位置不正确;还有一点,就是在tip提示的时候进行窗口的大小的拖动会导致tip的提示的延迟位置定位,及时拖动定位可以设置[refreshAniDuration:0]即可

    小知识:

      在进行监听$(window).resize(function(){dowork()}); 这样就会在整个拖动过程中导致dowork函数会被执行N次,显然我们只是想在拖动大小完成的时候执行一次就够了;可以用到事件的延迟执行,setTimeout;

    function throttle(method, context) {
                    clearTimeout(method.tId);
                    method.tId = setTimeout(function () {
                        method.call(context);
                    }, 100);
                }
    使用的时候
    $(window).resize(function(){ throttle(dowork) })
    构建一个执行顺序,如果100,有等待的,则取消,重新加载新的,这样只会在最后一次执行,当然你得控制事件间隔;
  • 相关阅读:
    (转)如何在一台电脑上开启多个tomcat 和配置让系统识别哪个具体的tomcat
    Moccakids-Tangram Puzzle 限免啦!
    iOS:OC Lib:MagicalRecord
    iOS Vuforia:TextReco 增加自己的单词库
    iOS:Tools:快速注释Doxygen
    聊聊分布式事务,再说说解决方案
    .NET Core 事件总线,分布式事务解决方案:CAP
    Glob 模式
    基于 Kong 和 Kubernetes 的 WebApi 多版本解决方案
    ASP.NET Core 身份验证(一)
  • 原文地址:https://www.cnblogs.com/jameslif/p/3466977.html
Copyright © 2011-2022 走看看