Как мне правильно проверить валидность формы в наблюдателе, когда данные модели изменяются вне формы в angularjs?

StackOverflow https://stackoverflow.com//questions/21034489

Вопрос

Я все еще новичок в 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';
        }
    });
}]);

Скрипка: http://jsfiddle.net/anpsince83/cK6cc/1/

Это было полезно?

Решение

Пользовательская директива - это правильный путь.Обычно по нескольким причинам рекомендуется помещать часы в директивы, а не в контроллеры.На высоком уровне одна из причин заключается в том, что Angular рекомендует контроллеры быть тонкими и работать только как связующее звено между представлением и службами.Но вы упираетесь в конкретную, интересную причину.

Контроллеры запускаются до того, как подключаются угловые директивы.Таким образом, ваш контроллер watch будет добавлен в список наблюдения раньше, чем Angular ngModelWatch() делает для myData. ngModelWatch() это место, где работает Angular $formatters (напоминая, что $formatters, среди прочего, это то, где проверка запускается, когда в модели происходит изменение).

Поскольку просмотры выполняются в том порядке, в котором они были добавлены в список просмотра, ваш контроллер $watch выполняется перед проверкой делается с помощью $formatters.

Если вы вместо этого поставите то же самое $watch внутри директивы это будет добавлено во время ссылки после ngModelWatch() был добавлен в список наблюдения.Таким образом директива содержит $watch будет выполнен после проверки сделано.

Вот обновленная скрипка где вы можете понаблюдать за порядком выполнения $formatters и каждый $watch.И вы увидите, что версия директивы работает так, как ожидалось, - запускается после $formatters.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top