Предотвращение тайм-аутов в приложениях Angular

#angularjs

#angularjs

Вопрос:

У меня есть проблема, которую я смог решить, используя тайм-аут. Это похоже на очень плохую практику, которая может привести к недостижимому беспорядку, и я ищу лучший способ решить эту проблему.

Есть идеи?

Надеюсь, понятный JSFiddle проблемы

 <div ng-app="test" ng-controller="Ctrl">
<form name="form">
    <input custom-validation type="text" ng-model="model" name="text" /> 
it should not allowed to send the word 'fail'
</form>
<button ng-click="fillAndSend()">Fill with 'fail' and send</button>
<button ng-click="send()">Send</button>
 <h1>Success: {{success}}</h1>
 
 angular.module('test', []);
angular.module('test').directive('customValidation', function () {
    'use strict';
    return {
        require: '?ngModel',
        link: function (scope, element, attrs, ngModelCtrl) {
            scope.$watch(attrs.ngModel, function (value) {
                if (value == 'fail') {
                    ngModelCtrl.$setValidity('customValidation', false);
                } else {
                    ngModelCtrl.$setValidity('customValidation', true);
                }
            });
        }
    };
});

angular.module('test').controller('Ctrl', function ($scope, $timeout) {
    $scope.success = false;
    $scope.model;
    $scope.fillAndSend = function() {
        $scope.model = 'fail';
        $scope.send();
        /* using a timeout works
        $timeout(function(){
            $scope.send();    
        },0);
        */
    }

    $scope.send = function () {
        if ($scope.form.$valid) {
            $scope.success = true;
        } else {
            $scope.success = false;
        }
    }
});
 

Ответ №1:

Я полагаю, это связано с тем, что цикл angular $ digest выполняется здесь только один раз. Использование $timeout заставляет вторую часть того, что вы делаете, выполнять второй цикл дайджеста, поэтому он работает с $timeout . Вы не можете просто вызвать $scope.$apply() , потому что вы уже находитесь в цикле дайджеста. В этом случае использование тайм-аута является правильным решением, потому что вам нужно, чтобы angular понял, что модель изменилась, а ЗАТЕМ вызвал функцию отправки.

Другой вариант — установить флаг в контроллере, который необходимо вызывать для отправки, поскольку вы меняете модель. А затем в вашей директиве, где вы просматриваете модель, вы можете проверить, нужно ли вызывать send

Комментарии:

1. Некоторые асинхронные службы и поставщики используют встроенный $timeout для запуска цикла $digest . Это аккуратный трюк, и в нем нет ничего плохого.

Ответ №2:

scope.$apply() может помочь :

  $scope.fillAndSend = function() {
    $scope.model = 'fail';
    $scope.$apply();
    $scope.send();
    /* using a timeout works
    $timeout(function(){
        $scope.send();    
    },0);
    */
}