Angular digest apply when setValidation

When I submit a form I do some backend validation to ensure that an email is unique as follows:

$http.post('/api/users.json', dataObj)
     .then (function() {
          // we are happy
      })
      .catch(function(response) {
           if(response.data.data.exception) {
                var emailNotUniqueException = 'App\Http\Exception\EmailNotUniqueException'; 
                $scope.userRegister.email.$setValidity("unique", false);
                scrollToFirstError();
            }
      }
);

The scrollToFirstError does what is says on the tin:

function scrollToFirstError () {
     var invalidInputs = angular.element('input.ng-invalid, select.ng-invalid');
     return invalidInputs.first().focus();
}

The problem of course is that although I can see ng-valid has been applied to the input the binding is lost I believe. I read about scope digest and apply, if I add either I get a message:

angular.js:14328 Error: [$rootScope:inprog] $digest already in progress

What am I doing wrong?

Answer

After you set the validity of a field to invalid, you have to wait until the current digest cycle is applied. If you don’t do so, the HTML might be not updated yet when you look for ng-invalid classes.

That being said, it is often a good idea to let the digests finish themselves and do not start or invoke them by hand, unless you really know you need this.

In this particular case, I would suggest you to call scrollToFirstError in the next digest cycle. It can be simply achieved with the $timeout service. Inject it first and then replace your scrollToFirstError() call with the following:

$timeout(scrollToFirstError);