10

I uses ng-repeat to get multiple phone numbers

<div ng-repeat="phone in phones">
    <input ng-model="phone" type="text" autofocus="autofocus"> 
</div>
<a ng-click="addPhone()">Add Phone</a>

In controllers

$scope.addPhone = function() {
    $scope.phones.add('');
}

Whenever i add new phone, it automatically autofocus the input. It works great. But when i reload(open from link) the view, it scrolls to last entry. How do i avoid autofocus at first time the view loads. Only i want to autofocus when i add new phone.

Fizer Khan
  • 88,237
  • 28
  • 143
  • 153

4 Answers4

19

Try:

<div ng-repeat="phone in phones">
    <input ng-model="phone" type="text" ng-if="$index == focusIndex" autofocus>
    <input ng-model="phone" type="text" ng-if="$index != focusIndex">
  </div>
  <a ng-click="addPhone()">Add Phone</a>

JS:

$scope.addPhone = function() {
    $scope.phones.push('Phone' + Math.random());

    $scope.focusIndex = $scope.phones.length-1;
  }

DEMO

Solution using custom attribute:

<div ng-repeat="phone in phones">
    <input ng-model="phone" type="text" custom-autofocus="$index == focusIndex" >
  </div>
  <a ng-click="addPhone()">Add Phone</a>

JS:

.directive('customAutofocus', function() {
  return{
         restrict: 'A',

         link: function(scope, element, attrs){
           scope.$watch(function(){
             return scope.$eval(attrs.customAutofocus);
             },function (newValue){
               if (newValue === true){
                   element[0].focus();//use focus function instead of autofocus attribute to avoid cross browser problem. And autofocus should only be used to mark an element to be focused when page loads.
               }
           });
         }
     };
})

DEMO

Rubens Mariuzzo
  • 28,358
  • 27
  • 121
  • 148
Khanh TO
  • 48,509
  • 13
  • 99
  • 115
  • 5
    Nice solution. Best practice is to not prefix custom directives with ng in case of clashes with future angular releases. – Gruff Bunny Jan 25 '14 at 17:07
  • 1
    I just tested this solution (DEMO plunker link ) with Chrome v52: I do not get the focus on the last INPUT ... Could this solution be obsolete? – Didier68 Sep 12 '16 at 15:08
  • @Didier68: you get focus only when you add new phone. If you want to have focus on page load, you need to set the default index to `focusIndex`: http://plnkr.co/edit/lN5W94oDeiqR6HMUFMqz?p=preview – Khanh TO Sep 16 '16 at 13:53
  • Instead using condition custom-autofocus="$index == focusIndex" just use custom-autofocus="$last" – user626710 Dec 07 '17 at 22:00
  • @user626710: your approach is fine in this case, but using a `focusIndex` is a more general approach – Khanh TO Dec 09 '17 at 02:51
3

You can use this directive: https://github.com/aikus/ng-focus-if/blob/master/ng-focus-if.js For example:

<div ng-repeat="phone in phones">
   <input ng-model="phone" type="text" ng-focus-if="1==1"> 
</div>
<a ng-click="addPhone()">Add Phone</a>
Nikita
  • 31
  • 1
1

What happens is you have a list of inputs that is demanding the focus when the page loads at the same time. Since the last input renders last, it always gets the autofocus.

The solution would be to apply the autofocus attribute when needed.

<div ng-repeat="phone in phones">
    <input ng-model="phone" type="text" autofocus="{{phone.autofocus || 'false'}}"> 
</div>
<a ng-click="addPhone()">Add Phone</a>

Controller:

$scope.addPhone = function() {
    $scope.phones[$scope.phones.length-1].autofocus = 'false'; // unfocus the old
    $scope.phones.add('');
    $scope.phones[$scope.phones.length-1].autofocus = 'true'; // focus the new
}
ncabral
  • 2,512
  • 1
  • 19
  • 20
  • This always focuses the element, even if the expression evaluates to 'false'. Using Chrome. – Sam Barnum Apr 09 '14 at 16:40
  • Boolean attributes in HTML are only false when they don't exist. http://stackoverflow.com/a/25449778/41908 – Rob Jan 24 '17 at 15:20
0

Having autofocus multiple times in your page is not forbidden, but does not look right based on the documentationm, https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input

It saysOnly one form element in a document can have the autofocus attribute

autofocus HTML5 This Boolean attribute lets you specify that a form control should have input focus when the page loads, unless the user overrides it, for example by typing in a different control. Only one form element in a document can have the autofocus attribute, which is a Boolean. It cannot be applied if the type attribute is set to hidden (that is, you cannot automatically set focus to a hidden control).

I would not to use autofocus within ng-repeat and set focus manually after it is added.

allenhwkim
  • 27,270
  • 18
  • 89
  • 122