類似的文章園子里已有,請看這裡,個人感覺稍顯複雜,日前也打算寫一個簡單的給項目用,一些關鍵點記錄於此。最終效果如下: 後端使用Asp.net mvc5,前端框架有:jquery.validate、jquery.validate.unobtrusive、requirejs、Bootstrap,都是當前 ...
類似的文章園子里已有,請看這裡,個人感覺稍顯複雜,日前也打算寫一個簡單的給項目用,一些關鍵點記錄於此。最終效果如下:
後端使用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安裝,具體怎麼用請繼續往下看。
首先在後臺我們定義實體類:
/// <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