私は非常によく似た問題を抱えていました。問題は、おそらくフィールド同士の関係をチェックしたくないということです。これを行うと、たとえば 2 月 30 日でない場合など、日付が実際に有効かどうかを確認するのが非常に難しくなります。やりたいことは、中間要素を介して日付全体をチェックすることです。
補足として、設計上、コントローラーはこの種のアクティビティに関与するべきではありません。検証はディレクティブ レベルで実行する必要があるため、再利用可能で Angular と一貫性があり、バリデータ チェーンの利点が得られます。たとえば、有効な日付だけをチェックする必要があるが、別の日付では生年月日を年齢でチェックする必要がある場合、コードを「濡らす」ことになります:)
私は、Angular の哲学にうまく適合する、合理的に単純な解決策を思いつきました。トリックは、3 つのドロップダウンすべてをまとめて、日付全体の検証を一度に実行する中間フォーム要素 (たとえば、非表示の入力) を使用することです。
フォーカスを設定するための 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/
役に立てば幸いです、Jacek