MVC與Validate驗證提示的樣式修改

  

  MVC中使用Validate的驗證,要修改錯誤提示樣式一共有3處須要修改,不然就不太完美了;html

  MVC中的Validate的驗證機制只用在後臺寫一次,就能夠完成前臺和後臺的完美驗證,前臺的驗證主要是依靠Validate.js來完成,Validate只是做爲一個驗證插件,可是錯誤提示是靠微軟的jquery.validate.unobtrusive.js這個js來完成,可是他只負責給錯誤的邊框加上紅色,且在後面出現一個span來顯示,有時候會撐壞佈局;jquery

  可使用自定義的驗證提示來作到比原始驗證漂亮的驗證提示;ajax

  先是找到一款tip提示的插件,有事件和方法進行tip提示的代碼控制顯示和隱藏及銷燬便可;poshytip:http://vadikom.com/demos/poshytip/# 還算不錯,基本能夠知足要求;app

  MVC的強類型提交表單處理好以後:ide

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="width:80px;text-align:right;">用戶</td>
                <td style="width:200px">
                    @Html.TextBoxFor(m => m.UserName)
                    @Html.ValidationMessageFor(m=>m.UserName)
                </td>
            </tr>
            <tr>
                <td style="width: 80px; text-align: right;">密碼</td>
                <td style="width: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>
    }
View Code

 

  注:ValidationMessageFor是必須得,由於錯誤提示的跟蹤點是在ValidationMessageFor生成的span上進行的;jquery、validate、validate. Unobtrusive這幾個js是必須得;佈局

 

  咱們只須要將validate.unobtrusive中進行錯誤消息提示時進行攔截便可;每次錯誤提示都會觸發validate.unobtrusive中的onError事件;咱們改寫以下就能夠:ui

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

  效果圖:this

  到此就完了嗎?在此錯誤提示,在鼠標離開或切換的時候,切實能夠進行相應的錯誤提示;spa

  如今需求變了,若是是不少單選按鈕組,須要至少選中一個怎麼辦了?若是不做任何修改,默認會在第一個按鈕上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);
        
    });
});
View Code

  使用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,有等待的,則取消,從新加載新的,這樣只會在最後一次執行,固然你得控制事件間隔;
相關文章
相關標籤/搜索