HTML5: How to set focus on a text input in a list

2020-02-07 02:47发布

I use AngularJS with the ng-repeat directive to show an array of objects as a list.

<li ng-repeat="cue in cues" class="form-inline">
    <input type="text" ng-model="cues[$index].text" class="input-xlarge"/>
    {{cue.isNewest}}
</li>

The property "isNewest" is true on only one element of the array. I would like to set the keyboard focus on the text input of that item. How can I do that with AngularJS?

4条回答
Root(大扎)
2楼-- · 2020-02-07 03:19

Here is another directive implementation that uses attrs.$observe:

myApp.directive('focus', function () {
  return function (scope, element, attrs) {
    attrs.$observe('focus', function (newValue) {
      newValue === 'true' && element[0].focus();
      // or, if you don't like side effects (see @Christophe's comment):
      //if(newValue === 'true')  element[0].focus();
    });
  }
});

Note that an interpolated DOM attribute value (i.e., {{cue.isNewest}}) always evaluates to a string, hence the reason newvalue is compared to the string 'true' rather than keyword true.

HTML:

<input type="text" ng-model="cues[$index].text" focus="{{cue.isNewest}}"
 class="input-xlarge" />{{cue.isNewest}}

This fiddle also has a method to toggle which item in the array should have the focus.

Note that if you do not load jQuery, we need to use element[0].focus() in the link function (not element.focus()) becaues jqLite doesn't have a focus() method.

查看更多
疯言疯语
3楼-- · 2020-02-07 03:25

The other proposed answers work OK 9/10 times for me, but soon I was running in "$digest already in progress" fun.

I have a slightly modified version of the previous answers by asgoth and Mark Rajcok. Basically you inject the $timeout dependency and put the focus() call inside of a timeout(...). IIRC ng-focus does the same.

var app = angular.module('cgeers', []);
app.directive('focus', ["$timeout", function ($timeout) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            scope.$watch(attrs.focus, function (value) {
                if (value) {
                    $timeout(function() { element[0].focus(); });
                }
            });
        }
    };
}]);
查看更多
做自己的国王
4楼-- · 2020-02-07 03:26

There is no special feature in AngularJS to receive focus. You could solve this with a $watch in your controller, but also with a directive.

查看更多
一纸荒年 Trace。
5楼-- · 2020-02-07 03:35

Since you would be manipulating the DOM, you will need to create a directive. Something like:

var app = angular.module('quirli', []);
app.directive('focusable', function() {
    return {
        restrict: 'A',
        scope: {
            focusable: '@'
        },
        link: function(scope, elm, attrs) {
            scope.$watch('focusable', function (value) {
                if (value) {
                    elm[0].focus();
                }
            });
        }
    };
});

Html:

<html ng-app="quirli" lang="en">
....  
<input type="text" ng-model="cues[$index].text" class="input-xlarge" focusable="{{cue.isNewest}}"/>

Note: untested.

查看更多
登录 后发表回答