日期类型输入框自定义校验异常及表单校验优化咨询
问题
我需要给type="date"的输入框实现自定义错误提示,规则如下:
- 输入框为必填项
- 填写的日期必须在1920年1月1日至去年今日(当前日期减一年)范围内
已编写代码如下:
输入框代码
<div class="form-group col-lg-5 desktop-margin"> <label for="DateofBirth" class="required-field">Date of birth</label> <input id="dob" name="dob" type="date" class="form-control" value="@Model.DateofBirth" data-val="true" data-rule-required="true" data-val-required="Date of birth is required." data-rule-customdate="true" data-val-customdate="Invalid date."> <div id="dobError" class="help-block field-validation-valid"></div> </div>
jQuery代码
$.validator.addMethod("customdate", function (value, element) { // 转换输入值为Date对象 var selectedDate = new Date(value); // 获取当前日期并计算一年前的日期 var currentDate = new Date(); var oneYearAgo = new Date(); oneYearAgo.setFullYear(currentDate.getFullYear() - 1); // 定义允许的最小/最大日期范围 var minDate = new Date("1920-01-01"); var maxDate = oneYearAgo; console.log("selectedDate is: " + selectedDate + " minimum date is: " + minDate + " maximum date is: " + maxDate); // 校验逻辑 if (isNaN(selectedDate)) { console.log("no date was provided"); createErrorSpan("Date of birth is required."); return false; } else if (selectedDate > maxDate) { console.log("date is big"); createErrorSpan("Date should occur before " + formatDate(maxDate) + "."); return false; } else if (selectedDate < minDate) { console.log("date is small"); createErrorSpan("Date should occur after " + formatDate(minDate) + "."); return false; } return true; }); // 自定义校验方法的适配器 $.validator.unobtrusive.adapters.add("customdate", function (options) { options.rules["customdate"] = true; options.messages["customdate"] = options.message; }); // 输入事件触发校验 $("#dob").on("input", function () { var isValid = $("#MyForm").valid(); console.log("input is triggered and its: " + isValid); if (isValid) { if ($("#dobError").has("span").length > 0) { $("#dobError").find("span").remove(); } } });
目前遇到的问题:customdate校验方法仅在输入有效日期时触发(比如输入2000-02-02,仅在输完最后一个字符时触发),输入无效日期(比如2033-02-02)时完全不执行。请问我遗漏了什么?另外有没有更好的方式替代$("#MyForm").valid(),避免触发表单内所有字段的校验?
解答
一、自定义校验不触发的原因
jQuery Validate默认会优先执行字段基础合法性校验,只有基础合法的字段才会触发自定义校验:
- 对于
type="date"的输入框,浏览器会做原生格式验证:只有输入内容符合标准日期格式(如YYYY-MM-DD)且为有效日期(不存在的日期如2033-02-30会被拦截),才会被判定为基础合法。 - 若输入无效日期,浏览器原生验证会直接标记字段非法,jQuery Validate会抛出内置格式错误,跳过你的自定义校验方法。
- 当字段为空时,
required规则会先触发错误,同样会跳过customdate方法。
解决办法
给表单添加novalidate属性,关闭浏览器原生验证,让所有校验逻辑由jQuery Validate接管:
<form id="MyForm" novalidate> <!-- 表单内容 --> </form>
同时调整自定义校验方法,将格式校验和范围校验合并,并且让空值交由required规则处理:
$.validator.addMethod("customdate", function (value, element) { // 空值交给required规则校验,这里直接返回true if (!value) return true; var selectedDate = new Date(value); // 更准确的日期有效性判断 if (isNaN(selectedDate.getTime())) return false; var currentDate = new Date(); // 精准计算去年今日(避免月份/日期溢出问题) var oneYearAgo = new Date(currentDate.getFullYear() - 1, currentDate.getMonth(), currentDate.getDate()); var minDate = new Date("1920-01-01"); return selectedDate >= minDate && selectedDate <= oneYearAgo; });
二、替代$("#MyForm").valid()的方案
如果你只想校验单个字段#dob,直接使用$(this).valid()即可,该方法只会校验当前字段,不会触发整个表单的校验:
$("#dob").on("input change", function () { var isValid = $(this).valid(); // 仅校验当前字段 console.log("input is triggered and its: " + isValid); if (isValid) { $("#dobError span").remove(); // 简化错误清除逻辑 } });
三、优化后的完整逻辑说明
- 关闭浏览器原生验证后,所有校验由jQuery Validate处理;
- 字段为空时,
required规则触发必填提示; - 字段格式错误时,
customdate方法返回false,触发自定义格式错误提示; - 字段格式正确但超出范围时,
customdate方法返回false,触发范围错误提示; - 输入/改变事件仅校验当前字段,不影响表单其他元素。
内容的提问来源于stack exchange,提问作者William
相关产品推荐
相关产品推荐

