6

I'm trying to use ng-blur on a <tr ng-blur="blurFn()"> but it doesn't fire. It fires only on the child <input> element.

This is not specific to <tr> or <td>. According to Angular documentation, ng-blur reacts to the blur event, which doesn't "bubble". "focusout" event bubbles, but there is no ng-focusout.

Am I missing something or do I need to create a new directive to handle focusout event?

Here's the code snippet and fiddle:

html

<div ng-app="App">
    <div ng-controller="Ctrl as ctrl">
        <table>
            <tr ng-repeat="item in ctrl.items" ng-blur="ctrl.blurFn()">
                <td><input ng-model="item.A"/></td>
                <td><input ng-model="item.B"/></td>
            </tr>
        </table>
    </div>
</div>

js

angular.module("App", [])
.controller("Ctrl", function(){
    this.blurFn = function($event){
        console.log($event.target);
    };

    this.items = [
        {A: "111", B: "222"},
        {A: "111", B: "222"},
        {A: "111", B: "222"},
        {A: "111", B: "222"},
        {A: "111", B: "222"}
        ];
});
PSL
  • 123,204
  • 21
  • 253
  • 243
New Dev
  • 48,427
  • 12
  • 87
  • 129

1 Answers1

4

One way would just be to create a focus out directive of your own.

angular.module("App", [])
.controller("Ctrl", function(){
    this.blurFn = function($event){
        console.log("Yay, blurred");
        this.name = "focessed out at" + $event.target.name;
    };
    
    this.items = [
        {A: "111", B: "222"},
        {A: "111", B: "222"},
        {A: "111", B: "222"},
        {A: "111", B: "222"},
        {A: "111", B: "222"}
        ];
//This is just the way other handlers are defined...
}).directive('focusout', ['$parse', function($parse) {
      return {
        compile: function($element, attr) {
          var fn = $parse(attr.focusout);
          return function handler(scope, element) {
            element.on('focusout', function(event) {
              scope.$apply(function() {
                 fn(scope, {$event:event});
              });
            });
          };
        }
      };
}]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
<div ng-app="App">
    
    <div ng-controller="Ctrl as ctrl">
        {{ctrl.name}}
        <table>
            <tr ng-repeat="item in ctrl.items" focusout="ctrl.blurFn($event)">
                <td><input ng-attr-name="A{{$index}}" ng-model="item.A"/></td>
                <td><input ng-attr-name="B{{$index}}" ng-model="item.B"/></td>
            </tr>
        </table>
    </div>
</div>

You may want to be aware of the fact that, focusout event is not supported in firefox.

PSL
  • 123,204
  • 21
  • 253
  • 243
  • 1
    Thanks for the example. Is there a good way to support this cross-browser? – New Dev Sep 20 '14 at 23:55
  • I just realized that my problems are not over. Even if I'm leaving the but staying within , I'm getting the focusout event – New Dev Sep 21 '14 at 00:02
  • @NewDev That is what focus out is, right, you wanted them to be bubbled, so even if you leave any input obviously they will bubble up (and there is no focusout/blur for tr, it is for the form elements not for every element in html), and it goes completely against your question now. – PSL Sep 21 '14 at 00:07
  • @NewDev You may want to probably rethink on what you are trying to do> What exactly are you trying to do? There could be a better solution. – PSL Sep 21 '14 at 00:12
  • Agreed. The question as asked was answered. – New Dev Sep 21 '14 at 00:15
  • @NewDev Leave marking apart :), what exactly is your goal? – PSL Sep 21 '14 at 00:16
  • What I'm trying to do is to create a datasheet-like table, which allows editing cells within rows (that corresponds to records in a database), and commit to database when row loses focus. – New Dev Sep 21 '14 at 00:16
  • DId you try wrapping each rows inputs ina form and attaching blur on form? – PSL Sep 21 '14 at 00:18
  • Unless I'm misunderstanding, it's against specifications to wrap a `` in a form or ``s. The only other way would be to place all the inputs in a single cell, but then I lose the benefits of a table for tabular data. – New Dev Sep 21 '14 at 00:26
  • Ofcourse yes :), You will have only one td and wrap elements in a form. But actually still i doubt, But check the specs https://developer.mozilla.org/en-US/docs/Web/Events/blur. Probably time to go bootstrap.. :) – PSL Sep 21 '14 at 00:27