自分で読んでチェックしたことから、AngularJS + カスタム検証についていくつか疑問があります。
- AngularJS は、単純なフィールド検証 (ng-require など) のための優れたヘルパーを提供します。
- 単一フィールドのカスタム検証を実装する最良の方法は、ディレクティブを使用することです (コントローラーを汚染しません)。
複数のファイルに影響を与えるカスタムのビジネス検証がある場合、私の疑問が生じます。次の簡単なシナリオを確認してみましょう。
- フライトの到着状況、フィールドを編集しています: 状況 (着陸/予定/遅延)、コメント (フライト状況に関する追加情報)。
適用したいビジネス検証は次のとおりです。コメント フィールドは、ステータス フィールドの値が「遅延」の場合にのみ必要です。
私がそれを実装した方法:
- ステータス + コメント フィールドの変更を処理するディレクティブを定義します ($watch によるステータス)。
このディレクティブは、ビジネス検証をサービスに委任します
このアプローチが私に与えていると思う利点は次のとおりです。
ビジネス サービスの検証が分離されます。
そのビジネス検証に単体テストを簡単に追加できます。
再利用でき、UI 要素に依存しません。
このサンプルを JSFiddle ( JSFiddle 検証サンプル) にコンパイルしました。
JS:
function MyCtrl($scope) {
$scope.arrival = {
"id": 1,
"originAirport": "Malaga (AGP)",
"flightNumber": "Iberia 132",
"dueAt": "2013-05-26T12:10:10",
"status": 2,
"info": "test"
}
}
myApp.directive('validateinfofield', ['formArrivalValidation', function (formArrivalValidation) {
return {
require: "ngModel",
link: function(scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift(function(viewValue){
// Empty? Let's check status
//if (!viewValue.length && scope.arrival.status == 3) {
if(formArrivalValidation.validateInfoField(scope.arrival.status, viewValue)) {
ctrl.$setValidity('validInfo', true);
} else {
ctrl.$setValidity('validInfo', false);
}
});
// Let's add a watch to arrival.status if the values change we need to
// reevaluate, if comments is empty and status is delayes display error
scope.$watch('arrival.status', function (newValue, oldValue) {
if (formArrivalValidation.validateInfoField(newValue, scope.editArrivalForm.txInfo.$viewValue)) {
ctrl.$setValidity('validInfo', true);
} else {
ctrl.$setValidity('validInfo', false);
}
});
}
};
}]);
// Validation Service, limited to our "business language"
myApp.factory('formArrivalValidation',
function () {
return {
validateInfoField: function (status, infoField) {
var isOk = true;
if (status == 3) {
if (infoField == undefined) {
isOk = false;
} else {
if (!infoField.length)
isOk = false;
}
}
return isOk;
},
};
});
これは従うべき良いアプローチですか?これを達成するためのより良い、より簡単な方法はありますか?