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安装,具体怎么用请继续往下看。

首先在后台我们定义实体类

rush:js;"> /// /// 厂家信息 /// public class Manufacturer : OperatedModel { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int ID { get; set; } /// /// 信用代码/注册号 /// [required(ErrorMessage = "信用代码/注册号不能为空")] [MaxLength(30)] public string EnterpriseNo { get; set; } /// /// 企业名称 /// [required(ErrorMessage = "企业名称不能为空")] public string EnterpriseName { get; set; } /// /// 注册地址 /// [required(ErrorMessage = "注册地址不能为空")] public string RegisteredAddress { get; set; } /// /// 法人 /// [required(ErrorMessage = "法人不能为空")] public string ArtificialPerson { get; set; } /// /// person in charge 负责人 /// [required(ErrorMessage = "负责人不能为空")] public string PIC { get; set; } [required(ErrorMessage = "手机号不能为空")] [RegularExpression(RegexLib.Mobile,ErrorMessage = "手机号码格式不正确")] public string Mobile { get; set; }

[EmailAddress]
public string Email { get; set; }
///


/// 商铺号
///

public string ShopNumber { get; set; }
///
/// 店铺管理员姓名
///

public string StoreManagerName { get; set; }
///
/// 店铺管理员联系方式
///

[RegularExpression(RegexLib.Mobile,ErrorMessage="手机号码格式不正确")]
public string StoreManagerNumber { get; set; }
///
/// 主要执照,三证合一营业执照
///

public string MainLicence { get; set; }
///
/// json,其他执照,如生产许可证
///

public string OtherLicence { get; set; }
///
/// 入驻日期
///

[required(ErrorMessage = "入驻日期不能为空")]
public DateTime EnterDate { get; set; }
///
/// 离场日期
///

[required(ErrorMessage = "截止日期不能为空")]
public DateTime QuitDate { get; set; }
///
/// 厂家可提现余额
///

public decimal Balance { get; set; }
}

实体各属性上面有Attribute形式的校验规则,当用户提交一个Model到后端Action时,MVC框架会据此自动帮我们完成校验工作,于是后端开发就很开心。然而在数据提交之前,前端也有必要进行第一轮的校验,如果使用jquery.validate,那么需要在js或标签里再写一遍类似的规则,能不能复用后端已有的代码呢?我们以属性EnterpriseNo为例,在cshtml中写:

m.BasicInfo.EnterpriseNo,new { placeholder = "必填项",@class = "form-control" })

最终生成的html如下:

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配置,代码

rush:js;"> 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):

rush: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 <a href="https://www.jb51.cc/tag/nothing/" target="_blank" class="keywords">nothing</a>
    //},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._con<a href="https://www.jb51.cc/tag/fig/" target="_blank" class="keywords">fig</a>Tooltip();
  this._con<a href="https://www.jb51.cc/tag/fig/" target="_blank" class="keywords">fig</a>Validator();
},_con<a href="https://www.jb51.cc/tag/fig/" target="_blank" class="keywords">fig</a>Tooltip: function () {
  $('[data-val="true"]').tooltip(this._tooltipOptions);
},_con<a href="https://www.jb51.cc/tag/fig/" target="_blank" class="keywords">fig</a>Validator: function () {
  $.validator.setDefaults(this._validatorOptions);
  $.validator.unobtrusive.parse(document);
}

}

return new TooltipValidator();
});

这样我们就可以在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种。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持

相关文章

页面搜索关键词突出 // 页面搜索关键词突出 $(function () {...
jQuery实时显示日期、时间 html: &lt;span id=&quot...
jQuery 添加水印 &lt;script src=&quot;../../../.....
中文:Sys.WebForms.PageRequestManagerParserErrorExceptio...
1. 用Response.Write方法 代码如下: Response.Write(&q...
Jquery实现按钮点击遮罩加载,处理完后恢复 思路: 1.点击按...