angularjs アプリケーションがあり、カスタム ビジネス ルールでフォームの検証を行う必要があります。問題は、特定の入力フィールドの検証ルールが他のフィールドに依存しており、実際のモデル値が変更されたとき以外に検証をトリガーする方法がわからないことです。
ケースは、従業員の動的リストであり、それぞれに入力する時間の動的リストがあります。ルールの 1 つは、これらの時間が重複してはならないということです。つまり、ある値が変更されたために別の値が無効になる可能性があり、その逆も同様です。また、フィールドごとにエラー メッセージを表示する必要があります。
フォームのコンテンツは、ネストされたリピーターのいくつかのレイヤーを持つデータモデルから生成されます。さまざまな検証ルールを含むカスタム ディレクティブを作成しました。そのフィールドが変更されたときに適切にトリガーされます。私は ngMessages を使用して、違反しているビジネス ルールに基づいて適切なエラー メッセージを表示しています。
問題は、特定の 1 つのフィールドが変更されたときに、他のすべてのフィールドで検証をトリガーするにはどうすればよいかということです。ある従業員の値は他の従業員の検証に影響を与えないため、値が変更されている従業員のすべてのフィールドの検証をトリガーすることをお勧めします。
ここのフィドルには、私の場合の単純化されたバージョンがあり、「重複」ルールは 2 つの数値が同じかどうかをチェックするだけです。
html:
<form name="demoForm">
<div ng-repeat="employee in list">
<div ng-bind="employee.name"></div>
<div ng-repeat="day in employee.days" ng-form="employeeForm">
<input ng-model="day.hours" name="hours" custom-validate="{day: day, days: employee.days}" ng-model-options="{allowInvalid:true}" />
<span ng-messages="employeeForm.hours.$error">
<span ng-message="number">Should be a number.</span>
<span ng-message="businessHours">The number is outside business hours.</span>
<span ng-message="max">The number is too large.</span>
<span ng-message="overlap">The number must be unique for each employee.</span>
</span>
</div>
<br/>
</div>
</form>
検証ディレクティブ:
angular.module('app').directive('customValidate', [validator]);
function validator() {
return {
restrict: 'A',
require: 'ngModel',
scope: {
data: '=customValidate'
},
link: linkFunc,
};
function linkFunc(scope, element, attrs, ctrl) {
ctrl.$validators.number = function(value) {
return value === "" || Number.isInteger(+value);
}
ctrl.$validators.businessHours = function(value) {
// imagine other validation data here
return value === "" || (value >= 1 && value <= 10);
}
ctrl.$validators.overlap = function(value) {
if (value === "") {
return true;
}
// find all other entries with identical value excluding self
var identical = scope.data.days.filter(function(x) {
return x !== scope.data.day && +x.hours === +value;
});
return identical.length === 0;
};
}
}