Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

$digest error when using ng-blur in an ng-if #4979

Closed
matthughes opened this issue Nov 15, 2013 · 6 comments
Closed

$digest error when using ng-blur in an ng-if #4979

matthughes opened this issue Nov 15, 2013 · 6 comments

Comments

@matthughes
Copy link

I have two input fields both set to autofocus. Each input field is inside an ng-if condition that is mutually exclusive. The condition starts out false showing the one input field, and when an http call finishes, the condition is set to true, removing one DOM and showing the other. When the initial one gets hid, it triggers the ng-blur event, but I get this exception:

Error: [$rootScope:inprog] $digest already in progress
http://errors.angularjs.org/1.2.0/$rootScope/inprog?p0=%24digest
    at https://192.168.20.248:8011/ui/dependencies/angular/angular.js:78:12
    at beginPhase (https://192.168.20.248:8011/ui/dependencies/angular/angular.js:11830:15)
    at Scope.$apply (https://192.168.20.248:8011/ui/dependencies/angular/angular.js:11627:11)
    at HTMLInputElement.<anonymous> (https://192.168.20.248:8011/ui/dependencies/angular/angular.js:17425:21)
    at HTMLInputElement.jQuery.event.dispatch (https://192.168.20.248:8011/ui/dependencies/jquery/jquery.js:5095:9)
    at HTMLInputElement.elemData.handle (https://192.168.20.248:8011/ui/dependencies/jquery/jquery.js:4766:28)
    at https://192.168.20.248:8011/ui/dependencies/angular-animate/angular-animate.js:875:54
    at forEach (https://192.168.20.248:8011/ui/dependencies/angular/angular.js:303:18)
    at getElementAnimationDetails (https://192.168.20.248:8011/ui/dependencies/angular-animate/angular-animate.js:871:11)
    at animateSetup (https://192.168.20.248:8011/ui/dependencies/angular-animate/angular-animate.js:957:23) 

HTML

        <div ng-controller="MyCtrl">
          <div ng-if="result">
            <form>
              <input type="text" required autofocus class="form-control" ng-blur="focusStolen()" />
              Result is back
            </form>
          </div>
          <div ng-if="!result">
            <form>
              <input type="text" required autofocus class="form-control" />
              Awaiting result
            </form
          </div>
        </div>

Script

var app = angular.module('myApp', []);
app.controller('MyCtrl', ['$scope', '$http', function($scope, $http) {

  function refresh() {
     $http.get('index.html').then(function() {
       $scope.result = true;
     });
  }

  refresh();
}]);
@petebacondarwin
Copy link
Contributor

A plunker demonstrating this (perhaps with $timeout if you don't want to get into using $http in the demo) would be useful.

@caitp
Copy link
Contributor

caitp commented Feb 20, 2014

As mentioned in #6364, the focus event may need to $evalAsync rather than $apply, in order to prevent issues with html5 autofocus (and possibly other situations)

@Narretz
Copy link
Contributor

Narretz commented Feb 20, 2014

related #5945

I tried the example in the above issue with $evalAsync and it works. Might have to try with other issues. Pull request wanted?

@Narretz
Copy link
Contributor

Narretz commented Feb 21, 2014

I can't reproduce this in a plunkr:
http://plnkr.co/edit/YSTK5qQcltDL1jtsmqIj?p=preview (best open in Chrome, FF does not autofocus correctly for me)

Neither httpBackend mocks nor timeout show the problem. Note also that the description does not match the example code: the blur should be on the element that is initially displayed.

@nbrustein
Copy link

The same problem exists in ngModelDirective's post method. Doesn't look like it's fixed by PR 6910

@btford btford removed the gh: issue label Aug 20, 2014
@tbosch
Copy link
Contributor

tbosch commented Aug 27, 2014

Ok, I will create a PR too that always uses scope.$evalAsync. Reasoning:

blur and focus events are fired in sync, i.e. if a focused input event is removed it triggers the blur event and calls our listener at an unexpected time. See this fiddle: http://jsfiddle.net/n2Lb8y2q/

Even if we are outside of angular and someone causes a blur/focus on an angular element with an angular event listener we should wait as the caller might also be in an unsafe code position where executing our listener would lead to unforeseen side effects.

tbosch added a commit to tbosch/angular.js that referenced this issue Aug 27, 2014
…$evalAsync`

BREAKING CHANGE:
The `blur` and `focus` event fire synchronously, also during DOM operations
that add/remove elements. This lead to errors as the Angular model was not
in a consistent state.

This change executes the expression of those events now asynchronously.

Related to angular#5945
Fixes angular#4979
tbosch added a commit to tbosch/angular.js that referenced this issue Aug 27, 2014
…$evalAsync`

BREAKING CHANGE:
The `blur` and `focus` event fire synchronously, also during DOM operations
that add/remove elements. This lead to errors as the Angular model was not
in a consistent state.

This change executes the expression of those events now asynchronously.

Fixes angular#4979
Fixes angular#5945
Closes angular#8803
Closes angular#6910
Closes angular#5402
tbosch added a commit to tbosch/angular.js that referenced this issue Aug 28, 2014
…$evalAsync`

BREAKING CHANGE:
The `blur` and `focus` event fire synchronously, also during DOM operations
that remove elements. This lead to errors as the Angular model was not
in a consistent state. See this [fiddle](http://jsfiddle.net/fq1dq5yb/) for a demo.

This change executes the expression of those events using
`scope.$evalAsync` if an `$apply` is in progress, otherwise
keeps the old behavior.

Fixes angular#4979
Fixes angular#5945
Closes angular#8803
Closes angular#6910
Closes angular#5402
tbosch added a commit to tbosch/angular.js that referenced this issue Aug 28, 2014
…$evalAsync`

BREAKING CHANGE:
The `blur` and `focus` event fire synchronously, also during DOM operations
that remove elements. This lead to errors as the Angular model was not
in a consistent state. See this [fiddle](http://jsfiddle.net/fq1dq5yb/) for a demo.

This change executes the expression of those events using
`scope.$evalAsync` if an `$apply` is in progress, otherwise
keeps the old behavior.

Fixes angular#4979
Fixes angular#5945
Closes angular#8803
Closes angular#6910
Closes angular#5402
@tbosch tbosch closed this as completed in 719c747 Aug 28, 2014
tbosch added a commit that referenced this issue Aug 29, 2014
…$evalAsync`

BREAKING CHANGE:
The `blur` and `focus` event fire synchronously, also during DOM operations
that remove elements. This lead to errors as the Angular model was not
in a consistent state. See this [fiddle](http://jsfiddle.net/fq1dq5yb/) for a demo.

This change executes the expression of those events using
`scope.$evalAsync` if an `$apply` is in progress, otherwise
keeps the old behavior.

Fixes #4979
Fixes #5945
Closes #8803
Closes #6910
Closes #5402
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants