Пользовательская проверка по AngularJS не срабатывает при программном изменении модели
Я создал специальный валидатор, требующий, чтобы дата была в прошлом. Валидация, похоже, отлично работает при вводе даты вручную в поле. Однако, если я вводю изменения даты программным путем (измените модель напрямую, а не набирать в поле), проверка не срабатывает.
Я считаю, что я выполняю собственную директиву проверки, как указано в документации. Вот jsFiddle, иллюстрирующий проблему. В скрипке, если вы нажмете кнопку "Изменить дату программно", вы увидите, что ошибка проверки не отображается (но это происходит, если вы меняете ее вручную). Вот код директивы (также в скрипке):
myApp.directive('pastDate', function() {
return {
restrict: 'A',
require: '?ngModel',
link: function (scope, element, attrs, ctrl) {
ctrl.$parsers.unshift(function (viewValue) {
var today = new Date();
today = new Date(today.getFullYear(), today.getMonth(), today.getDate());
if (new Date(viewValue) < today) {
ctrl.$setValidity('pastDate', true);
return viewValue;
}
ctrl.$setValidity('pastDate', false);
return undefined;
});
}
};
});
Ответы
Ответ 1
Существует два способа привязки модели, $parsers
управляет конвейером направления "вид-модель", а $formatters
управляет конвейером направления модели для просмотра. Когда вы обновляете модель в контроллере, изменение проходит через конвейер $formatters
.
Я обновил ваш код до: this, поэтому он обрабатывает оба способа.
myApp.directive('pastDate', function() {
return {
restrict: 'A',
require: '?ngModel',
link: function (scope, element, attrs, ctrl) {
function validate (value) {
var today = new Date();
today = new Date(today.getFullYear(), today.getMonth(), today.getDate());
if (new Date(value) < today) {
ctrl.$setValidity('pastDate', true);
return value;
}
ctrl.$setValidity('pastDate', false);
return value;
}
ctrl.$parsers.unshift(validate);
ctrl.$formatters.unshift(validate)
}
};
});
Ответ 2
Новый ответ с angular 1.3 предоставляет свойство $validators
.
Так как 1.3, $parsers
и $formatters
больше не должны устанавливать силу, даже если это возможно.
Затем ваш код станет проще:
myApp.directive('pastDate', function() {
return {
restrict: 'A',
require: '?ngModel',
link: function (scope, element, attrs, ctrl) {
ctrl.$validators.pastDate = function(modelValue) { // 'pastDate' is the name of your custom validator ...
var today = new Date();
today = new Date(today.getFullYear(), today.getMonth(), today.getDate());
return (new Date(modelValue) < today);
}
}
};
});
Обновлен jsFiddle: http://jsfiddle.net/jD929/53/