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 intentio
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();
}
}
});
}
};
});
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();
});
};
});
This defines an attribute focus-iter
to be set on the parent element of all the repeated inputs. See this in action here: http://jsbin.com/ahugeg/10/.
The advantage over @Trevor's is that I can set an arbitrary selector for the value of focus-iter
attribute to specify exactly which elements the focus jumping should work with. As a crazy example, try setting focus-iter
attribute to input:even
:). This helps since in my application, the input
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);
}
});
}
}
})