次のバリデータ ディレクティブがあります。
directive('myValidate', function($timeout) {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
if(!scope.requirementSpec){
scope.requirementSpec = {};
}
if(Boolean(attrs.valueRequired) || Boolean(attrs.minLength) && elm[0].value != ""){
console.log(scope.model[attrs.name]);
ctrl.$setValidity(attrs.name, false);
// elm.removeClass('ng-valid').addClass('ng-invalid');
}
elm.on('focus', function(){
console.log(elm);
console.log(ctrl);
var form = elm.parents().find('form');
// $timeout(function(){$ctrl.$dirty = true;}, 0);
});
ctrl.$parsers[0] = (function(viewValue) {
scope.valid = true;
scope.fieldName = attrs.name;
var nameStr = attrs.name + '';
var nameObj = nameStr.split('_');
for(var i = 0; i < nameObj.length; ++i){
nameObj[i] = nameObj[i].substr(0, 1).toUpperCase() + nameObj[i].slice(1);
}
var nameStrParsed = nameObj.join(' ');
scope.fieldErrorDisplay = Boolean(nameStrParsed) ? nameStrParsed : 'This field';
if(attrs.valueRequired && viewValue.length == 0 && !attrs.minLength){
scope.valid = false;
scope.requirementSpec[nameStr] = [{
'msg' : scope.fieldErrorDisplay + ' is required',
'class' : undefined
}];
}
else{
// scope.fieldErrorDisplayObj[nameStr] = scope.fieldErrorDisplay + ' must meet the following requirements: ';
scope.requirementSpec[nameStr] = [];
if(attrs.minLength){
var itemValidity = viewValue.length >= attrs.minLength;
scope.valid = !itemValidity ? false : scope.valid;
var item = {
'msg' : 'At Least ' + attrs.minLength + ' Chars',
'class' : itemValidity ? 'valid' : undefined
};
scope.requirementSpecrequirementSpec[nameStr].push(item);
}
else if(attrs.valueRequired){
var itemValidity = viewValue && viewValue.length >= 1;
scope.valid = !itemValidity ? false : scope.valid;
var item = {
'msg' : 'This field must be filled',
'class' : itemValidity ? 'valid' : undefined
};
scope.requirementSpec[nameStr].push(item);
}
if(attrs.maxLength){
var itemValidity = viewValue.length <= attrs.maxLength;
scope.valid = !itemValidity ? false : scope.valid;
var item = {
'msg' : attrs.maxLength + ' Chars At Most ',
'class' : itemValidity ? 'valid' : undefined
};
scope.requirementSpec[nameStr].push(item);
}
if(attrs.minLetters){
var itemValidity = (viewValue && /[A-z]/.test(viewValue));
scope.valid = !itemValidity ? false : scope.valid;
var item = {
'msg' : 'Must contain at least ' + attrs.minLetters + ' letters',
'class' : itemValidity ? 'valid' : undefined
};
scope.requirementSpec[nameStr].push(item);
}
if(attrs.minNumbers){focus
var itemValidity = (viewValue && /\d/.test(viewValue));
scope.valid = !itemValidity ? false : scope.valid;
var item = {
'msg' : 'Must contain at least' + attrs.minNumbers + ' numbers',
'class' : itemValidity ? 'valid' : undefined
};
scope.requirementSpec[nameStr].push(item);
}
}
if(scope.valid) {
var errorsPresent = false;
for(var i = 0; i < scope.requirementSpec[nameStr].length; i++){
if(!scope.requirementSpec[nameStr][i].class){
errorsPresent = true;
}
}
scope.requirementSpec[nameStr] = errorsPresent ? scope.requirementSpec[nameStr] : [];
ctrl.$setValidity(nameStr, true);
elm.removeClass('ng-required-invalid').removeClass('validatorError').removeClass('ng-invalid').addClass('ng-valid');
return viewValue;
} else {
ctrl.$setValidity(nameStr, false);
return undefined;
}
});
}
};
}).
ご覧のとおり、リンク関数では、このディレクティブを適用する入力要素の値が空かどうかを確認し、この要素の有効性を false に設定します。
問題は、このディレクティブを使用して編集フォームを検証するときに発生します。編集フォームでは、REST リソースへの XHR 要求によって値が取得されます。
私の質問は、これをどのように処理し、このロジックをフィールドの ng-model にバインドするかです。これらのそれぞれを個別に監視するのではなく、ひどい無駄になります。
おそらく、ユーザー入力を指示するだけでなく、フィールドのモデルの変更に反応するように $parser を作成できますか?.