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

nBlur causes "$digest already in progress" when ngRepeat causes the blur event #5401

Closed
mike-schenk opened this issue Dec 13, 2013 · 9 comments

Comments

@mike-schenk
Copy link

When a focused input element that has an ng-blur directive is disconnected from the DOM by the ng-repeat directive, a "$digest already in progress" error is thrown.

See this JSFiddle for a repro: http://jsfiddle.net/Cq7NJ/5/

@caitp
Copy link
Contributor

caitp commented Dec 13, 2013

I'm not seeing this happen in your reproduction, is this browser specific? Oh I see, nevermind

@mike-schenk
Copy link
Author

This happens in Chrome. It doesn't seem to be happening in Firefox or IE.

@caitp
Copy link
Contributor

caitp commented Dec 13, 2013

Yeah hmm, I wonder if this can be solved without adding "safeApply" to ngEventDirs. I'll poke around at it on the weekend or on monday I guess, because there's probably a better way.

@petebacondarwin
Copy link
Contributor

I think the better way to fix this - without resorting to the non-public $$phase approach is to use $timeouts.
This is how it is done in the AngularJS docs app: https://github.com/angular/angular.js/blob/master/docs/src/templates/js/docs.js#L118-L133

@ghost ghost assigned IgorMinar Dec 20, 2013
@IgorMinar
Copy link
Contributor

it seems that under certain circumstances blur event is fired synchronously while we are making DOM changes within an apply.

I wonder if safeapply might cause all kinds of weird timing issues here.

I actually think that we should try not to cause the blur event (it doesn't look like it should be triggered in this case since the element should remain focused). I don't know if this is a possibility.

If the issue doesn't happen on Firefox and IE it's also possible that it's a chrome bug. Someone should check what the spec actually says about this behavior (should the browser trigger blur when an item is being moved and should it trigger it synchronously?).

@mike-schenk
Copy link
Author

Section 7.4.2 says

When an element that is focused stops being a focusable element, or stops being focused without another element being explicitly focused in its stead, the user agent should synchronously run the unfocusing steps for the affected element only.
For example, this might happen because the element is removed from its Document, or has a hidden attribute added. It would also happen to an input element when the element gets disabled.

When ng-repeat decides to rearrange the DOM elements, it has to temporarily detach some elements before putting them in their final place. If it detaches an element that is focused, we have the problem.

So I think Chrome is behaving according to spec and IE and Firefox are not.

And yes, in my specific case using an ng-repeat where we just want to reorder the elements, I would prefer that the blur is never fired and focus would remain in the moved input box. I think the ng-repeat and/or $animate service it uses would have to get really smart to be able to handle that.

@warrenbell
Copy link

Has there been any update or workaround on this issue ? I am having the same problem with a ng-blur in a ng-repeat where the items get rearranged. I do not know enough about Angular's internals to try and fix this on my own. Thanks

@quazzie
Copy link
Contributor

quazzie commented Feb 6, 2014

Getting the same problem, any update ?

@mike-schenk
Copy link
Author

I have not pursued this issue. I don't believe anything has changed, nor do I believe anything is going to change. I'm unclear about what direction the angular maintainers want to go.

For the project I am working on, we have just made our own blur directive by copying the original angular one and applying the fix in my pull request and it's not causing us any more problems.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.