Sharing Top Content from the Angular-sphere.

[SOLVED] Change focus to input on a key event in AngularJS- Angular.js Recipes

  • In the above test case, I have three input elements, generated by directive.
  • My intention in this test case, is that hitting the up/down arrows in one of these inputs should move focus to the input in the corresponding direction, if there is an input available in that direction.
  • Anyway, I defined two new directives ( and ), to handle the up and down events and am calling the and methods, passing the correct entry, relative to which the focus should move.
  • I know it is not the angular-way to deal with DOM elements in controllers, but I can’t see how the focus can be seen as an attribute/property of a model.
  • Even if I do and I detect changes, how can I access the input element corresponding to the entry I want focused?

I just wrote this up and tested it briefly – it does what you want without all the extra clutter in your controller and in the HTML. See it working here.

HTML:

<body ng-controller=”Ctrl”>
<input ng-repeat=”entry in entries” value=”{{entry}}” key-focus />
</body>

Controller:

function Ctrl($scope) {
$scope.entries = [ ‘apple’, ‘ball’, ‘cow’ ];
}

Directive:

app.directive(‘keyFocus’, function() {
return {
restrict: ‘A’,
link: function(scope, elem, attrs) {
elem.bind(‘keyup’, function (e) {
// up arrow
if (e.keyCode == 38) {
if(!scope.$first) {
elem[0].previousElementSibling.focus();
}
}
// down arrow
else if (e.keyCode == 40) {
if(!scope.$last) {
elem[0].nextElementSibling.focus();
}
}
});
}
};
});


@angular_recipe: Change focus to input on a key event in AngularJS #Angular #AngularJS

Test case: http://jsbin.com/ahugeg/4/edit (Slightly long)

In the above test case, I have three input elements, generated by

ng-repeat

directive. My intention in this test case, is that hitting the up/down arrows in one of these inputs should move focus to the input in the corresponding direction, if there is an input available in that direction.

I am new to AngularJS, so I might be missing on some straightforward way to do this. Anyway, I defined two new directives (

on-up

and

on-down

), to handle the up and down events and am calling the

and

methods, passing the correct entry, relative to which the focus should move. This is where I am stuck.

I know it is not the angular-way to deal with DOM elements in controllers, but I can’t see how the focus can be seen as an attribute/property of a model. I even thought of having a separate

, but then should I watch for changes on that property? Even if I do and I detect changes, how can I access the input element corresponding to the entry I want focused?

Any help on how this should be done are very much appreciated.

I just wrote this up and tested it briefly – it does what you want without all the extra clutter in your controller and in the HTML. See it working here.

HTML:

Controller:

function Ctrl($scope) { $scope.entries = [ ‘apple’, ‘ball’, ‘cow’ ]; }

Directive:

app.directive(‘keyFocus’, function() { return { restrict: ‘A’, link: function(scope, elem, attrs) { elem.bind(‘keyup’, function (e) { // up arrow if (e.keyCode == 38) { if(!scope.$first) { elem[0].previousElementSibling.focus(); } } // down arrow else if (e.keyCode == 40) { if(!scope.$last) { elem[0].nextElementSibling.focus(); } } }); } }; });

Inspired by @Trevor’s solution, here’s what I settled on,

app.directive(‘focusIter’, function () { return function (scope, elem, attrs) { var atomSelector = attrs.focusIter; elem.on(‘keyup’, atomSelector, function (e) { var atoms = elem.find(atomSelector), toAtom = null; for (var i = atoms.length – 1; i >= 0; i–) { if (atoms[i] === e.target) { if (e.keyCode === 38) { toAtom = atoms[i – 1]; } else if (e.keyCode === 40) { toAtom = atoms[i + 1]; } break; } } if (toAtom) toAtom.focus(); }); elem.on(‘keydown’, atomSelector, function (e) { if (e.keyCode === 38 || e.keyCode === 40) e.preventDefault(); }); }; });

to be set on the parent element of all the repeated inputs. See this in action here: http://jsbin.com/ahugeg/10/.

s come with quite a bit of extra markup around them, unlike the test case.

I had a similar problem and used this simple directive. It works as ng-show and ng-hide would- only with focus, if it’s attribute resolves as true:

.directive(‘focusOn’,function() { return { restrict : ‘A’, link : function($scope,$element,$attr) { $scope.$watch($attr.focusOn,function(focusVal) { if(focusVal === true) { setTimeout(function() { $element.focus(); },50); } }); } } })

Angular.js Recipes are structured in a Cookbook format featuring recipes that contain problem statements and solutions. A detailed explanation follows each problem statement of the recipe. This is usually contained within the solution; however, an optional discussion section can often contain other useful information helping to demonstrate how the solution works.

Angular.js is a JavaScript-based open-source front-end web application framework mainly maintained by Google and by a community of individuals and corporations to address many of the challenges encountered in developing single-page applications. The JavaScript components complement Apache Cordova, the framework used for developing cross-platform mobile apps. It aims to simplify both the development and the testing of such applications by providing a framework for client-side model–view–controller (MVC) and model–view–viewmodel (MVVM) architectures, along with components commonly used in rich Internet applications.

Lost? Begin by working through Angular’s Getting Started Guide to get yourself up-and-running.

[SOLVED] Change focus to input on a key event in AngularJS- Angular.js Recipes

Comments are closed, but trackbacks and pingbacks are open.