我有一个非常相似的问题。问题是,您可能不想检查彼此相关的字段。如果您这样做,则很难确定日期是否实际有效,例如,如果不是 2 月 30 日。您要做的是通过中间元素检查整个日期。
作为旁注 - 根据设计,控制器不应参与此类活动。验证应该在指令级别完成,因此它是可重用的并且与 Angular 一致,为您提供验证器链的好处。例如,如果您只需要检查一个有效日期,但在另一个中您需要检查出生日期的年龄,那么您最终会“弄湿”您的代码:)
我想出了一个相当简单的解决方案,它非常适合 Angular 哲学。诀窍是使用中间表单元素(例如隐藏输入),它将所有三个下拉列表组合在一起并一次性对整个日期执行验证。
这是用于设置焦点的 HTML:
<form name="dateForm" novalidation>
<input type="hidden"
ng-model="modelDate"
date-type-multi="viewDate"
ng-init="viewDate = {}"
class="form-control"
/>
<select ng-model="viewDate.day">
<option value="">select day</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="18">18</option>
<option value="19">19</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="28">28</option>
<option value="29">29</option>
<option value="30">30</option>
<option value="31">31</option>
</select>
<select ng-model="viewDate.month">
<option value="">select month</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
</select>
<select ng-model="viewDate.year">
<option value="">select year</option>
<option value="1981">1981</option>
<option value="1982">1982</option>
<option value="1983">1983</option>
<option value="1984">1984</option>
<option value="1985">1985</option>
<option value="1986">1986</option>
<option value="1987">1987</option>
<option value="1988">1988</option>
<option value="1989">1989</option>
<option value="1990">1990</option>
<option value="1991">1991</option>
<option value="1992">1992</option>
</select>
</form>
和JS代码:
angular.module('dateApp', []).
directive('dateTypeMulti', function() {
return {
priority: -1000,
require: 'ngModel',
link: function(scope, elem, attrs, ngModel) {
ngModel.$render = function() {
angular.extend(scope.$eval(attrs.dateTypeMulti), ngModel.$viewValue);
};
scope.$watch(attrs.dateTypeMulti, function(viewValue) {
ngModel.$setViewValue(viewValue);
}, true);
ngModel.$formatters.push(function(modelValue) {
if (!modelValue) return;
var parts = String(modelValue).split('/');
return {
year: parts[0],
month: parts[1],
day: parts[2]
};
});
ngModel.$parsers.unshift(function(viewValue) {
var isValid = true,
modelValue = '',
date;
if (viewValue) {
date = new Date(viewValue.year, viewValue.month - 1, viewValue.day);
modelValue = [viewValue.year, viewValue.month, viewValue.day].join('/');
if ('//' === modelValue) {
modelValue = '';
} else if (
date.getFullYear() != viewValue.year ||
date.getMonth() != viewValue.month - 1 ||
date.getDate() != viewValue.day) {
isValid = false;
}
}
ngModel.$setValidity('dateTypeMulti', isValid);
return isValid ? modelValue : undefined;
});
}
};
});
在指令上设置低优先级很重要,因为这样解析器将作为第一个触发(与格式化程序的工作顺序相反),并且该字段上的其他验证器将获得解析日期。
你可以在这里玩它:http:
//codepen.io/jciolek/pen/oxBch
我在这里详细描述了思考过程:http:
//float-middle.com/multiple-fields-validation-in-angularjs/
我希望它有帮助,杰克