天天看點

jquery.validate[.unobtrusive]和Bootstrap實作tooltip錯誤提示

類似的文章園子裡已有,請看這裡,個人感覺稍顯複雜,日前也打算寫一個簡單的給項目用,一些關鍵點記錄于此。最終效果如下:

jquery.validate[.unobtrusive]和Bootstrap實作tooltip錯誤提示

後端使用Asp.net mvc5,前端架構有:jquery.validate、jquery.validate.unobtrusive、requirejs、Bootstrap,都是目前最/較新版本。jquery.validate就不用說了,目前比較流行的前端校驗元件;jquery.validate.unobtrusive基于jquery.validate,是為了配合Asp.net mvc,微軟自己寫的,NuGet下可查找Microsoft.jQuery.Unobtrusive.Validation安裝,具體怎麼用請繼續往下看。

首先在背景我們定義實體類:

jquery.validate[.unobtrusive]和Bootstrap實作tooltip錯誤提示

/// <summary>
/// 廠家資訊
/// </summary>
public class Manufacturer : OperatedModel
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; }
    /// <summary>
    /// 信用代碼/注冊号
    /// </summary>
    [Required(ErrorMessage = "信用代碼/注冊号不能為空")]
    [MaxLength(30)]
    public string EnterpriseNo { get; set; }
    /// <summary>
    /// 企業名稱
    /// </summary>
    [Required(ErrorMessage = "企業名稱不能為空")]
    public string EnterpriseName { get; set; }
    /// <summary>
    /// 注冊位址
    /// </summary>
    [Required(ErrorMessage = "注冊位址不能為空")]
    public string RegisteredAddress { get; set; }
    /// <summary>
    /// 法人
    /// </summary>
    [Required(ErrorMessage = "法人不能為空")]
    public string ArtificialPerson { get; set; }
    /// <summary>
    /// person in charge 負責人
    /// </summary>
    [Required(ErrorMessage = "負責人不能為空")]
    public string PIC { get; set; }
    [Required(ErrorMessage = "手機号不能為空")]
    [RegularExpression(RegexLib.Mobile, ErrorMessage = "手機号碼格式不正确")]
    public string Mobile { get; set; }
        
    [EmailAddress]
    public string Email { get; set; }
    /// <summary>
    /// 商鋪号
    /// </summary>
    public string ShopNumber { get; set; }
    /// <summary>
    /// 店鋪管理者姓名
    /// </summary>
    public string StoreManagerName { get; set; }
    /// <summary>
    /// 店鋪管理者聯系方式
    /// </summary>
    [RegularExpression(RegexLib.Mobile, ErrorMessage="手機号碼格式不正确")]
    public string StoreManagerNumber { get; set; }
    /// <summary>
    /// 主要執照, 三證合一營業執照
    /// </summary>
    public string MainLicence { get; set; }
    /// <summary>
    /// json, 其他執照,如生産許可證
    /// </summary>
    public string OtherLicence { get; set; }
    /// <summary>
    /// 入駐日期
    /// </summary>
    [Required(ErrorMessage = "入駐日期不能為空")]
    public DateTime EnterDate { get; set; }
    /// <summary>
    /// 離場日期
    /// </summary>
    [Required(ErrorMessage = "截止日期不能為空")]
    public DateTime QuitDate { get; set; }
    /// <summary>
    /// 廠家可提現餘額
    /// </summary>
    public decimal Balance { get; set; }
}      

實體定義

實體各屬性上面有Attribute形式的校驗規則,當使用者送出一個Model到後端Action時,MVC架構會據此自動幫我們完成校驗工作,于是後端開發就很開心。然而在資料送出之前,前端也有必要進行第一輪的校驗,如果使用jquery.validate,那麼需要在js或标簽裡再寫一遍類似的規則,能不能複用後端已有的代碼呢?我們以屬性EnterpriseNo為例,在cshtml中寫:

@Html.TextBoxFor(m => m.BasicInfo.EnterpriseNo, new { placeholder = "必填項", @class = "form-control" })

最終生成的html如下:

<input class="form-control" data-val="true" data-val-maxlength="字段 EnterpriseNo 必須是最大長度為“30”的字元串或數組類型。" data-val-maxlength-max="30" data-val-required="信用代碼/注冊号不能為空" id="BasicInfo_EnterpriseNo" name="BasicInfo.EnterpriseNo" placeholder="必填項" value="" data-original-title="" title="" type="text">

标簽裡面自動加上了很多data-開頭的屬性,data-val表示該控件需要校驗,其它data-開頭的就是一系列校驗規則和失敗時的錯誤資訊,錯誤資訊可以自定義,否則架構會給你生成類如“字段 EnterpriseNo 必須是最大長度為30的字元串或數組類型。”這種機器翻譯語言。當然這些屬性jquery.validate是不認的,要讓jquery.validate認識,就需要jquery.validate.unobtrusive出馬了。

現在我們來說這些js如何配合使用。

新版本的jquery.validate已經支援AMD模式,是以可以直接使用requirejs加載,jquery.validate.unobtrusive則不行,需要shim配置,代碼:

require.config({
            baseUrl: '/scripts',
            paths: {
                "jquery": 'jquery-2.2.3.min',
                "knockout":'knockout-3.4.0',
                "bootstrap":'../components/bootstrap/3.3.6/js/bootstrap.min','validate':'jquery.validate',
                'validateunobtrusive':'jquery.validate.unobtrusive.min'
            },
            shim : {
                'bootstrap' : {
                    deps : [ 'jquery' ],
                    exports : 'bootstrap'
                },
                'validateunobtrusive':{
                    deps:['validate'],
                    exports: 'validateunobtrusive'
                }
            }
        });      

配置好後,在頁面中require,此時點選submit按鈕送出表單,各js就開始作用了。但是除了焦點會落到第一個校驗失敗的控件上,似乎并沒有其它效果,連jquery.validate預設的在控件後面展示錯誤資訊(errorPlacement函數)都沒有了,are you kidding me?其實這是因為jquery.validate.unobtrusive覆寫了errorPlacement配置項(看源碼中的attachValidation函數),對我們來說反而省了一道工序。由于tooltip的html标記是由bootstrap動态生成的,是以errorPlacement并不适合我們,參考本文開頭的連結,選擇覆寫showErrors函數,核心代碼如下(tooltipvalidator.js):

1 define(['validateunobtrusive'], function () {
 2 
 3     function TooltipValidator() {}
 4 
 5     TooltipValidator.prototype = {
 6         init: function (validatorOptions, tooltipOptions) {
 7             tooltipOptions = tooltipOptions || {};
 8             validatorOptions = validatorOptions || {};
 9 
10             this._tooltipOptions = $.extend({}, {
11                 placement: 'top'
12             }, tooltipOptions, { animation: false });
13 
14             this._validatorOptions = $.extend({}, {
15 
16                 //errorPlacement: function (error, element) {
17                 //    // do nothing
18                 //},
19 
20                 showErrors: function (errorMap, errorList) {
21                     for (var i = 0; i < this.successList.length; i++) {
22                         var success = this.successList[i];
23                         $(this.successList[i]).tooltip('destroy');
24                         $(this.successList[i]).parents('div.form-group').removeClass('has-error');
25                     }
26                     for (var i = 0; i < errorList.length; i++) {
27                         var errorElement = $(errorList[i].element);
28                         errorElement.parents('div.form-group').addClass('has-error');
29                         errorElement.attr('data-original-title', errorList[i].message).tooltip('show');
30                     }
31                 },
32 
33                 submitHandler: function (form) {
34                     return false;
35                 }
36 
37             }, validatorOptions)
38 
39             this._configTooltip();
40             this._configValidator();
41         },
42 
43         _configTooltip: function () {
44             $('[data-val="true"]').tooltip(this._tooltipOptions);
45         },
46 
47         _configValidator: function () {
48             $.validator.setDefaults(this._validatorOptions);
49             $.validator.unobtrusive.parse(document);
50         }
51     }
52 
53     return new TooltipValidator();
54 });      

這樣我們就可以在require回調函數中執行tooltipvalidator.init,不需要另外再寫邏輯,于是前端同學也開心的笑了。這裡還有一處需要注意,大家看到第49行代碼,這是初始化jquery.validate.unobtrusive的步驟。原本jquery.validate.unobtrusive在其代碼中已經有$(function () { $jQval.unobtrusive.parse(document); });但是由于$.ready會在Dom元素加載完成後(題外話:不是渲染完成)就執行,是以它會在tooltipvalidator有機會_configValidator之前完成,導緻咱們的配置項無效(如果是在單頁無重新整理應用中,會發現之後再次加載局部頁時,配置項有效了,因為$.ready隻在初次加載的時候執行,而require回調會每次加載都執行)。有兩種解決方法:1、讓jquery.validate.unobtrusive依賴tooltipvalidator;2、移除jquery.validate.unobtrusive中的$jQval.unobtrusive.parse(document);這裡選擇第2種。

很久沒寫博文,這次是寫的最快的了,20分鐘搞定,後續可能會有修改。

轉載請注明本文出處:http://www.cnblogs.com/newton/p/6011006.html

繼續閱讀