9

I am fairly experience with Angular by now, but this appears to be something happening at a lower level with the way DOM events are propagated. For some reason in just part of my application I have ng-focus and ng-blur on the same input, but the ng-focus event fires twice and the ng-blur never fires.

<input type="text" ng-focus="doFocus()" ng-blur="doBlur()" />

Then in my controller

$scope.doFocus = function(){
    console.log('focus');
}

$scope.doBlur = function(){
    console.log('blur');
 }

When I inspect my console, I see 2 "focus" and no "blur" messages... I have tested this in other parts of my website and it works in some others. My guess is it has something to do with the DOM, but I have even tried pulling out basically everything on the page except the input and it still didn't work correctly. Does anyone have any idea what could cause this?

UPDATE

After some more debugging, I noticed that the focus event is fired once in the scope of the browser, but the event triggers twice in the world of AngularJS. I set a breakpoint on all Focus events using Chrome Dev Tools and it only would hit once, but if I log the Angular $event in the console, I can see the EXACT same $event with the same timestamp being triggered twice in Angular.

Matt Hintzke
  • 7,744
  • 16
  • 55
  • 113
  • Can you create a jsfiddle of the issue? – Mathew Berg Jan 06 '15 at 18:49
  • No thats the problem.. it works just fine in other places. I know it is definitely just my code. I don't expect an exact solution response, it am more trying to see if this has happened before to anyone or if anyone with a higher level of knowledge of the underlying DOM spec would know – Matt Hintzke Jan 06 '15 at 18:50
  • If it's specific to your code, please paste more of your code. – Mathew Berg Jan 06 '15 at 18:51
  • I don't know how I can really.. I took everything out of my ANgularJS app except for the `input`. All parent DOM to my app is ASP .NET .ascx pages – Matt Hintzke Jan 06 '15 at 18:56
  • Ok so I just tested it in Firefox instead of Chrome and it worked just fine...WTF.. usually chrome is the best ha. I am really confused now – Matt Hintzke Jan 06 '15 at 19:00
  • Also confirmed it works in IE. Now I am really scared – Matt Hintzke Jan 06 '15 at 19:01

5 Answers5

15

Ok.. so this is kind of a strange one. After not finding a solution myself, I had a coworker try to reproduce my problem on his machine. Of course, it worked just fine for him.. this made me think it was my Chrome, so I uninstalled and re-installed a fresh instance of Chrome and now it everything is just fine... not sure what happened to my Chrome that caused the DOM events to get all kinds of messed up, but at least I figured it out.

Hopefully this helps anyone that may have this problem in the future.

UPDATE

I realized the problem was the Chrome Extension: AngularJS Batarang

This plugin was messing with my DOM events and caused them to not fire correctly. I removed the extension from Chrome and everything started working!

Community
  • 1
  • 1
Matt Hintzke
  • 7,744
  • 16
  • 55
  • 113
  • 1
    I ran into the exact same problem as you on Chrome Version 39.0.2171.99 (64-bit). The behavior is fine on Canary and Firefox.. – Jesse Jan 19 '15 at 18:11
  • @Jesse Do you have a Chrome Extension called AngularJS Batarang? if so, remove it and try – Matt Hintzke Jan 21 '15 at 20:53
  • Same problem! WTF @ angular batarang. I also fixed the problem by going el.find('input').bind('blur', fn).bind('focus', fn); but this only works if there is one input element in the directive :) – harelpls Mar 25 '15 at 04:02
  • Holy crap! I have just been wrestling with this problem for hours! I've been trying to undo all kinds of unrelated changes that I made trying to get to the bottom of this... it turned out that it was simply because at some point I had hit "enable" on the AngularJS tab in Chrome's dev tools. – Rich Apr 14 '15 at 14:35
  • While Batarang may be the cause for this, for me it was another directive on the same element that 'messed' with the focus of that input. Specifically it was the [focus-me directive](http://stackoverflow.com/questions/14833326/how-to-set-focus-on-input-field/14837021#14837021). – Shahar Feb 02 '17 at 14:04
2

This was driving me nuts until I discovered that it is a known bug with angular-batarang. See: https://github.com/angular/angularjs-batarang/issues/211. (Please star the issue if it is still not fixed when you read this.)

With batarang installed and enabled, only the first declared ng-blur or ng-focus will fire.

E.g. if you have,

    <input ng-blur='onBlur()' ng-focus='onFocus()'>

you will get the blur event but not the focus event. If you have,

    <input ng-focus='onFocus()' ng-blur='onBlur()'>

you will get the focus event but not the blur event.

If you are hitting this problem, until it is fixed the workaround is just to disable batarang when you are working with these events using the "Enable" checkbox shown here:

Image showing batarang disabled

Rich
  • 997
  • 9
  • 12
2

Updated Note: I answered this in 2016 before Angular 2.0 was a thing. So keep that in mind. This may not apply to you...

Just in case you're like me and don't read the docs...

You can't just apply on-blur/on-focus to any element. There are limited form elements as well as the window object that support it. Doesn't work on lots of other tag types... one more reason either of these 2 events might not fire...

Mike
  • 916
  • 12
  • 14
0

You must have something else wrong in your code.

When trying this:

<div ng-app="app" ng-controller="appCtrl">
    <input type="text" ng-focus="doFocus()" ng-blur="doBlur()" />
</div>

angular.module('app',[]).
controller('appCtrl', function($scope){
    $scope.doFocus = function(){
        console.log('focus');
    }

    $scope.doBlur = function(){
        console.log('blur');
    }
});

It works just fine. Check it out here.

Amir Popovich
  • 29,350
  • 9
  • 53
  • 99
  • Yeah I have tried it out in Plunker and other parts of my site that use the same version of jQuery/AngularJS/etc... I know it must be a DOM configuration problem, but I have no way of testing because my Angular apps are just sub-sites within a larger ASP .NET site. So it makes it hard to tell what DOM is causing this – Matt Hintzke Jan 06 '15 at 18:48
  • What angularjs version are you using on your application? – Amir Popovich Jan 06 '15 at 18:49
  • Ok..You need to post some more code or try to rep. this on JSFIDDLE somehow..i – Amir Popovich Jan 06 '15 at 18:52
  • yeah I have been trying to repro it. and I can't really post more code – Matt Hintzke Jan 06 '15 at 18:55
0

This can also happen with other extensions installed. In my case ng-blur was firing twice when I clicked on a radio button. One click, two blur events - no matter if the radio had already been selected.

After some testing, I discovered that AdBlock was the problem. This is slightly problematic; I cannot assume my users won't have it. I have to assume the radio buttons will always blur twice.

I will keep looking for another workaround.

durron597
  • 31,968
  • 17
  • 99
  • 158
NFlourish
  • 66
  • 7
  • Welcome to Stack Overflow! It's not important *how* you found the error, just that future users know what the solution was so it can help them in the future. I have edited your post to remove the information that was hiding the answer in your post. – durron597 Sep 11 '15 at 02:16