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

perf(input): prevent multiple $digest when input is blurred #8450

Closed
wants to merge 1 commit into from
Closed

perf(input): prevent multiple $digest when input is blurred #8450

wants to merge 1 commit into from

Conversation

guzart
Copy link
Contributor

@guzart guzart commented Aug 1, 2014

@kevinjamesus86 noticed that the input control would trigger a $digest
cycle every time it was blurred, adcc5a0#commitcomment-7129512.

After the control is in a $touched state, other $digest cycles are
unnecesary.

References #7673

@kevinjamesus86 noticed that the input control would trigger a $digest
cycle every time it was blurred, adcc5a0#commitcomment-7129512.

After the control is in a $touched state, other $digest cycles are
unnecesary.

References #7673
guzart referenced this pull request Aug 1, 2014
Sets the ngModel controller property $touched to True and $untouched to False whenever a 'blur' event is triggered over a control with the ngModel directive.
Also adds the $setTouched and $setUntouched methods to the NgModelController.

References #583
@mary-poppins
Copy link

I'm sorry, but I wasn't able to verify your Contributor License Agreement (CLA) signature. CLA signature is required for any code contributions to AngularJS.

Please sign our CLA and ensure that the CLA signature email address and the email address in this PR's commits match.

If you signed the CLA as a corporation, please let us know the company's name.

Thanks a bunch!

PS: If you signed the CLA in the past then most likely the email addresses don't match. Please sign the CLA again or update the email address in the commit of this PR.
PS2: If you are a Googler, please sign the CLA as well to simplify the CLA verification process.

@@ -2182,6 +2182,8 @@ var ngModelDirective = function() {
}

element.on('blur', function(ev) {
if (modelCtrl.$touched) return;

scope.$apply(function() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not $evalAsync or $timeout instead?

Using $apply, at least in our directive is causing Error: [$rootScope:inprog] $apply already in progress since we are setting focus to other input during a current $apply which will at the same time make this blur event run and cause the error.

Here's plunker with the problem

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The recommended way to execute an expression in Angular from outside angular realm (DOM events) is to use scope.$apply.

The error in your directive comes from line 244 when the close method, which is executed inside the angular realm (a $digest cycle), calls a DOM method (focus()). Any other directive that binds to the focus DOM event and attempts to execute an expression in the angular realm using $apply will cause an $apply already in progress exception.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants