Как мне правильно проверить валидность формы в наблюдателе, когда данные модели изменяются вне формы в angularjs?
-
21-12-2019 - |
Вопрос
Я все еще новичок в AngularJS, и я думаю, что у меня возникли проблемы с пониманием времени с помощью $scope.В контроллере я настроил наблюдателя для некоторых данных модели, которые привязаны к различным элементам формы.Наблюдатель запускает ajax-запрос при изменении данных, за исключением случаев, когда форма недействительна.Я проверяю валидность формы с помощью myForm.$valid.Однако все это довольно просто, за исключением случаев, когда данные модели обновляются в контроллере, а не в форме.Проверки выполняются, как и ожидалось, но form.$valid по-прежнему имеет предыдущее значение, а не то, каким оно должно быть с обновленными данными.Например, если форма была ранее действительной, то я удаляю значение модели, привязанное к требуемому вводу, наблюдатель сработает, потому что данные модели изменились, но когда я регистрирую значение myForm.$valid, это значение по-прежнему равно true, хотя оно должно быть false.
Итак, мой вопрос таков: A.почему это происходит?, но что более важно B.каков правильный способ справиться с тем, чего я пытаюсь достичь?Будет ли пользовательская директива иметь смысл?
Вот упрощенный пример.
HTML:
<div ng-controller="MyCtrl">
<form name="myForm">
<input type="text" name="myField" ng-model="myData" required>
<button type="button" ng-click="myData=''">Delete</button>
</form>
<div>
The watcher says the form is: <strong>{{ formStatus }}</strong>
</div>
</div>
Контроллер:
myApp.controller('MyCtrl', ['$scope', function($scope) {
$scope.myData = 'abc';
$scope.formStatus = '';
$scope.$watch('myData', function(newVal, oldVal) {
if (newVal != oldVal) {
console.log("my data changed");
console.log("my form valid = ", $scope.myForm.$valid);
$scope.formStatus = $scope.myForm.$valid ? 'Valid' : 'Invalid';
}
});
}]);
Решение
Пользовательская директива - это правильный путь.Обычно по нескольким причинам рекомендуется помещать часы в директивы, а не в контроллеры.На высоком уровне одна из причин заключается в том, что Angular рекомендует контроллеры быть тонкими и работать только как связующее звено между представлением и службами.Но вы упираетесь в конкретную, интересную причину.
Контроллеры запускаются до того, как подключаются угловые директивы.Таким образом, ваш контроллер watch будет добавлен в список наблюдения раньше, чем Angular ngModelWatch()
делает для myData
. ngModelWatch()
это место, где работает Angular $formatters
(напоминая, что $formatters
, среди прочего, это то, где проверка запускается, когда в модели происходит изменение).
Поскольку просмотры выполняются в том порядке, в котором они были добавлены в список просмотра, ваш контроллер $watch
выполняется перед проверкой делается с помощью $formatters
.
Если вы вместо этого поставите то же самое $watch
внутри директивы это будет добавлено во время ссылки после ngModelWatch()
был добавлен в список наблюдения.Таким образом директива содержит $watch
будет выполнен после проверки сделано.
Вот обновленная скрипка где вы можете понаблюдать за порядком выполнения $formatters
и каждый $watch
.И вы увидите, что версия директивы работает так, как ожидалось, - запускается после $formatters
.