jquery.validate[.unobtrusive]和Bootstrap實(shí)現(xiàn)tooltip錯(cuò)誤提示問題分析
類似的文章已有,請(qǐng)看這里,個(gè)人感覺稍顯復(fù)雜,日前也打算寫一個(gè)簡(jiǎn)單的給項(xiàng)目用,一些關(guān)鍵點(diǎn)記錄于此。最終效果如下:

后端使用Asp.net mvc5,前端框架有:jquery.validate、jquery.validate.unobtrusive、requirejs、Bootstrap,都是當(dāng)前最/較新版本。jquery.validate就不用說了,目前比較流行的前端校驗(yàn)組件;jquery.validate.unobtrusive基于jquery.validate,是為了配合Asp.net mvc,微軟自己寫的,NuGet下可查找Microsoft.jQuery.Unobtrusive.Validation安裝,具體怎么用請(qǐng)繼續(xù)往下看。
首先在后臺(tái)我們定義實(shí)體類:
/// <summary>
/// 廠家信息
/// </summary>
public class Manufacturer : OperatedModel
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
/// <summary>
/// 信用代碼/注冊(cè)號(hào)
/// </summary>
[Required(ErrorMessage = "信用代碼/注冊(cè)號(hào)不能為空")]
[MaxLength(30)]
public string EnterpriseNo { get; set; }
/// <summary>
/// 企業(yè)名稱
/// </summary>
[Required(ErrorMessage = "企業(yè)名稱不能為空")]
public string EnterpriseName { get; set; }
/// <summary>
/// 注冊(cè)地址
/// </summary>
[Required(ErrorMessage = "注冊(cè)地址不能為空")]
public string RegisteredAddress { get; set; }
/// <summary>
/// 法人
/// </summary>
[Required(ErrorMessage = "法人不能為空")]
public string ArtificialPerson { get; set; }
/// <summary>
/// person in charge 負(fù)責(zé)人
/// </summary>
[Required(ErrorMessage = "負(fù)責(zé)人不能為空")]
public string PIC { get; set; }
[Required(ErrorMessage = "手機(jī)號(hào)不能為空")]
[RegularExpression(RegexLib.Mobile, ErrorMessage = "手機(jī)號(hào)碼格式不正確")]
public string Mobile { get; set; }
[EmailAddress]
public string Email { get; set; }
/// <summary>
/// 商鋪號(hào)
/// </summary>
public string ShopNumber { get; set; }
/// <summary>
/// 店鋪管理員姓名
/// </summary>
public string StoreManagerName { get; set; }
/// <summary>
/// 店鋪管理員聯(lián)系方式
/// </summary>
[RegularExpression(RegexLib.Mobile, ErrorMessage="手機(jī)號(hào)碼格式不正確")]
public string StoreManagerNumber { get; set; }
/// <summary>
/// 主要執(zhí)照, 三證合一營(yíng)業(yè)執(zhí)照
/// </summary>
public string MainLicence { get; set; }
/// <summary>
/// json, 其他執(zhí)照,如生產(chǎn)許可證
/// </summary>
public string OtherLicence { get; set; }
/// <summary>
/// 入駐日期
/// </summary>
[Required(ErrorMessage = "入駐日期不能為空")]
public DateTime EnterDate { get; set; }
/// <summary>
/// 離場(chǎng)日期
/// </summary>
[Required(ErrorMessage = "截止日期不能為空")]
public DateTime QuitDate { get; set; }
/// <summary>
/// 廠家可提現(xiàn)余額
/// </summary>
public decimal Balance { get; set; }
}
實(shí)體各屬性上面有Attribute形式的校驗(yàn)規(guī)則,當(dāng)用戶提交一個(gè)Model到后端Action時(shí),MVC框架會(huì)據(jù)此自動(dòng)幫我們完成校驗(yàn)工作,于是后端開發(fā)就很開心。然而在數(shù)據(jù)提交之前,前端也有必要進(jìn)行第一輪的校驗(yàn),如果使用jquery.validate,那么需要在js或標(biāo)簽里再寫一遍類似的規(guī)則,能不能復(fù)用后端已有的代碼呢?我們以屬性EnterpriseNo為例,在cshtml中寫:
@Html.TextBoxFor(m => m.BasicInfo.EnterpriseNo, new { placeholder = "必填項(xiàng)", @class = "form-control" })
最終生成的html如下:
<input class="form-control" data-val="true" data-val-maxlength="字段 EnterpriseNo 必須是最大長(zhǎng)度為“30”的字符串或數(shù)組類型。" data-val-maxlength-max="30" data-val-required="信用代碼/注冊(cè)號(hào)不能為空" id="BasicInfo_EnterpriseNo" name="BasicInfo.EnterpriseNo" placeholder="必填項(xiàng)" value="" data-original-title="" title="" type="text">
標(biāo)簽里面自動(dòng)加上了很多data-開頭的屬性,data-val表示該控件需要校驗(yàn),其它data-開頭的就是一系列校驗(yàn)規(guī)則和失敗時(shí)的錯(cuò)誤信息,錯(cuò)誤信息可以自定義,否則框架會(huì)給你生成類如“字段 EnterpriseNo 必須是最大長(zhǎng)度為30的字符串或數(shù)組類型。”這種機(jī)器翻譯語(yǔ)言。當(dāng)然這些屬性jquery.validate是不認(rèn)的,要讓jquery.validate認(rèn)識(shí),就需要jquery.validate.unobtrusive出馬了。
現(xiàn)在我們來(lái)說這些js如何配合使用。
新版本的jquery.validate已經(jīng)支持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'
}
}
});
配置好后,在頁(yè)面中require,此時(shí)點(diǎn)擊submit按鈕提交表單,各js就開始作用了。但是除了焦點(diǎn)會(huì)落到第一個(gè)校驗(yàn)失敗的控件上,似乎并沒有其它效果,連jquery.validate默認(rèn)的在控件后面展示錯(cuò)誤信息(errorPlacement函數(shù))都沒有了,are you kidding me?其實(shí)這是因?yàn)閖query.validate.unobtrusive覆蓋了errorPlacement配置項(xiàng)(看源碼中的attachValidation函數(shù)),對(duì)我們來(lái)說反而省了一道工序。由于tooltip的html標(biāo)記是由bootstrap動(dòng)態(tài)生成的,所以errorPlacement并不適合我們,參考本文開頭的鏈接,選擇覆寫showErrors函數(shù),核心代碼如下(tooltipvalidator.js):
define(['validateunobtrusive'], function () {
function TooltipValidator() {}
TooltipValidator.prototype = {
init: function (validatorOptions, tooltipOptions) {
tooltipOptions = tooltipOptions || {};
validatorOptions = validatorOptions || {};
this._tooltipOptions = $.extend({}, {
placement: 'top'
}, tooltipOptions, { animation: false });
this._validatorOptions = $.extend({}, {
//errorPlacement: function (error, element) {
// // do nothing
//},
showErrors: function (errorMap, errorList) {
for (var i = 0; i < this.successList.length; i++) {
var success = this.successList[i];
$(this.successList[i]).tooltip('destroy');
$(this.successList[i]).parents('div.form-group').removeClass('has-error');
}
for (var i = 0; i < errorList.length; i++) {
var errorElement = $(errorList[i].element);
errorElement.parents('div.form-group').addClass('has-error');
errorElement.attr('data-original-title', errorList[i].message).tooltip('show');
}
},
submitHandler: function (form) {
return false;
}
}, validatorOptions)
this._configTooltip();
this._configValidator();
},
_configTooltip: function () {
$('[data-val="true"]').tooltip(this._tooltipOptions);
},
_configValidator: function () {
$.validator.setDefaults(this._validatorOptions);
$.validator.unobtrusive.parse(document);
}
}
return new TooltipValidator();
});
這樣我們就可以在require回調(diào)函數(shù)中執(zhí)行tooltipvalidator.init,不需要另外再寫邏輯,于是前端同學(xué)也開心的笑了。這里還有一處需要注意,大家看到第49行代碼,這是初始化jquery.validate.unobtrusive的步驟。原本jquery.validate.unobtrusive在其代碼中已經(jīng)有$(function () { $jQval.unobtrusive.parse(document); });但是由于$.ready會(huì)在Dom元素加載完成后(題外話:不是渲染完成)就執(zhí)行,因此它會(huì)在tooltipvalidator有機(jī)會(huì)_configValidator之前完成,導(dǎo)致咱們的配置項(xiàng)無(wú)效(如果是在單頁(yè)無(wú)刷新應(yīng)用中,會(huì)發(fā)現(xiàn)之后再次加載局部頁(yè)時(shí),配置項(xiàng)有效了,因?yàn)?.ready只在初次加載的時(shí)候執(zhí)行,而require回調(diào)會(huì)每次加載都執(zhí)行)。有兩種解決方法:1、讓jquery.validate.unobtrusive依賴tooltipvalidator;2、移除jquery.validate.unobtrusive中的$jQval.unobtrusive.parse(document);這里選擇第2種。
感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
相關(guān)文章
jQuery使用zTree插件實(shí)現(xiàn)樹形菜單和異步加載
這篇文章主要介紹了jQuery使用zTree插件實(shí)現(xiàn)樹形菜單和異步加載的相關(guān)方法,感興趣的小伙伴們可以參考一下2016-02-02
jQuery高級(jí)編程之js對(duì)象、json與ajax用法實(shí)例分析
這篇文章主要介紹了jQuery高級(jí)編程之js對(duì)象、json與ajax用法,結(jié)合實(shí)例形式分析了js對(duì)象的創(chuàng)建、使用,json格式數(shù)據(jù)轉(zhuǎn)換及ajax交互等相關(guān)操作技巧,需要的朋友可以參考下2019-11-11
jQuery中setTimeout的幾種使用方法小結(jié)
jQuery 中 setTimeout/setInterval 不能像在原生態(tài) javascript 中那樣使用, 否則會(huì)報(bào)錯(cuò).2013-04-04
jquery仿QQ商城帶左右按鈕控制焦點(diǎn)圖片切換滾動(dòng)效果
jquery圖片特效制作仿騰訊QQ商城首頁(yè)banner焦點(diǎn)圖片輪播切換效果,帶索引按鈕控制和左右按鈕控制圖片切換,實(shí)例代碼如下,感興趣的朋友可以參考下哈2013-06-06
關(guān)于jQuery object and DOM element
本篇文章,小編將為大家介紹,關(guān)于jQuery object and DOM element,有需要的朋友可以參考一下2013-04-04
Jquery利用mouseenter和mouseleave實(shí)現(xiàn)鼠標(biāo)經(jīng)過彈出層且可以點(diǎn)擊
這篇文章主要介紹了Jquery利用mouseenter和mouseleave實(shí)現(xiàn)鼠標(biāo)經(jīng)過彈出層且可以點(diǎn)擊。需要的朋友可以過來(lái)參考下,希望對(duì)大家有所幫助2014-02-02

