1

I have a table with input in each cell, I can add records to that table by clicking on a button. I would like to set focus on the first input of the last record created. I don't know if that's possible. If anyone can help me on this...

function Ctrl($scope) {
  $scope.adresses = [];
  
  $scope.add = function() {
    var adr = {ville:null, codePostal:null}
    $scope.adresses.push(adr);
  };
  
}
<!doctype html>
<html ng-app>
  <head>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.min.js"></script>
    <script src="script.js"></script>

  </head>
  <body>

<div ng-controller="Ctrl" >
  <button ng-click="add()"> Add </button>
  <table>
    <tr>
      
      <th>ville</th>
      <th>adresse</th>
    <tr>
    
    <tr ng-repeat="adresse in adresses">
      <td>
       <input ng-model="adresse.ville"/>
      </td>
      <td>
       <input ng-model="adresse.codePostal"/>
      </td>
      
     
    <tr>
  </table>
  
</div>






  </body>
</html>
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
user1260928
  • 3,269
  • 9
  • 59
  • 105
  • Take a look at [this question](http://stackoverflow.com/questions/14833326/how-to-set-focus-on-input-field), I think it basically does what you want. You can use `$last` property inside `ng-repeat` to detect whether to set focus or not. – Ilya Luzyanin Mar 31 '15 at 15:51

2 Answers2

4

Try this approach.

Controller

controller('AppCtrl', function ($scope, $timeout, $element) {
  $scope.adresses = [];

  $scope.add = function() {
    var adr = {ville:null, codePostal:null}
    $scope.adresses.push(adr);

    $timeout(function () {
      $element[0].querySelector('[is-last=true]').focus();
    })
  };
});

Markup

<input ng-model="adresse.ville" is-last="{{$last}}"/>

Working Plnkr

Vinay K
  • 5,562
  • 1
  • 18
  • 27
1

Yes, very easily doable with a directive:

My example with your code: http://plnkr.co/edit/aDNdjjBKZHVfTXnLy2VZ?p=preview

// the directive I use
.directive('focusOnMe', ['$timeout', '$parse',
        function($timeout, $parse) {
            return {
                //scope: true,   // optionally create a child scope
                link: function(scope, element, attrs) {
                    var model = $parse(attrs.focusOnMe);
                    scope.$watch(model, function(value) {
                        // console.log('value=',value);
                        if(value === true) {
                            $timeout(function() {
                                element[0].focus();
                            });
                        }
                    });
                }
            };
        }
]);

The HTML: the condition for focus is a boolean value, here it is whether the element is last. So each time you add a new row, the condition is re-evaluated and focus is assigned.

<td>
       <input ng-model="adresse.ville" focus-on-me="$last"/>
</td>
SoluableNonagon
  • 11,541
  • 11
  • 53
  • 98
  • looks like a nice solution, but... I am adding elements in my table from a modal. When the modal shows, the table behind freezes because the directive is called a lot of times. I can't reproduce this behavior in a plunkr. So I guess this problem is specific to my project. – user1260928 Apr 01 '15 at 07:59
  • The freezing is likely called just due to watchers and insertion of lots of html into the DOM at once. The simple solution is to use vanilla JS to find the last row and focus on the first input each time you add. This way you'd bypass directives altogether. But this wouldn't really speed up your code, it would still call focus on the last element each time you add one. May be mitigated by creating a timeout on the focus. But still, ng-repeat with lots of data and watchers is the true enemy. – SoluableNonagon Apr 01 '15 at 15:21