I\'m trying to navigate thru a list of records using only keyboard. When the page loads, the default \"focus\" should be on the first record, when the user clicks the down a
You could create a table navigation service which tracks the current row and exposes navigation methods to modify the current row's value and sets focus to the row.
Then all you would need to do is create a key binding directive where you could track key down events and fire the exposed methods from the table navigation service, on key up or key down.
I have used a controller to link the service methods to the key binding directive via a configuration object called 'keyDefinitions'.
You can extend the keyDefinitions to include the Enter key (Code: 13) and hook on to the selected $index value via the service property 'tableNavigationService.currentRow' or '$scope.data', then pass it as a parameter to your own custom submit() function.
I hope that this is helpful to somebody.
I have posted my solution to this issue at the following plunker location:
Keyboard Navigation Service Demo
HTML:
first name
last name
birth date
balance
email
{{row.firstName | uppercase}}
{{row.lastName}}
{{row.birthDate | date}}
{{row.balance | currency}}
email
CONTROLLER:
app.controller('navigationDemoController', [
'$scope',
'tableNavigationService',
navigationDemoController
]);
function navigationDemoController($scope, tableNavigationService) {
$scope.data = tableNavigationService.currentRow;
$scope.keyDefinitions = {
'UP': navigateUp,
'DOWN': navigateDown
}
$scope.rowCollection = [
{
firstName: 'Chris',
lastName: 'Oliver',
birthDate: '1980-01-01',
balance: 100,
email: 'chris@email.com'
},
{
firstName: 'John',
lastName: 'Smith',
birthDate: '1976-05-25',
balance: 100,
email: 'chris@email.com'
},
{
firstName: 'Eric',
lastName: 'Beatson',
birthDate: '1990-06-11',
balance: 100,
email: 'chris@email.com'
},
{
firstName: 'Mike',
lastName: 'Davids',
birthDate: '1968-12-14',
balance: 100,
email: 'chris@email.com'
}
];
$scope.activeRowIn = function(index) {
return index === tableNavigationService.currentRow;
};
function navigateUp() {
tableNavigationService.navigateUp();
};
function navigateDown() {
tableNavigationService.navigateDown();
};
function init() {
tableNavigationService.setRow(0);
};
init();
};
})();
SERVICE AND DIRECTIVE:
(function () {
'use strict';
var app = angular.module('tableNavigation', []);
app.service('tableNavigationService', [
'$document',
tableNavigationService
]);
app.directive('keyWatch', [
'$document',
keyWatch
]);
// TABLE NAVIGATION SERVICE FOR NAVIGATING UP AND DOWN THE TABLE
function tableNavigationService($document) {
var service = {};
// Your current selected row
service.currentRow = 0;
service.table = 'tableId';
service.tableRows = $document[0].getElementById(service.table).getElementsByTagName('tbody')[0].getElementsByTagName('tr');
// Exposed method for navigating up
service.navigateUp = function () {
if (service.currentRow) {
var index = service.currentRow - 1;
service.setRow(index);
}
};
// Exposed method for navigating down
service.navigateDown = function () {
var index = service.currentRow + 1;
if (index === service.tableRows.length) return;
service.setRow(index);
};
// Expose a method for altering the current row and focus on demand
service.setRow = function (i) {
service.currentRow = i;
scrollRow(i);
}
// Set focus to the active table row if it exists
function scrollRow(index) {
if (service.tableRows[index]) {
service.tableRows[index].focus();
}
};
return service;
};
// KEY WATCH DIRECTIVE TO MONITOR KEY DOWN EVENTS
function keyWatch($document) {
return {
restrict: 'A',
link: function(scope) {
$document.unbind('keydown').bind('keydown', function(event) {
var keyDefinitions = scope.keyDefinitions;
var key = '';
var keys = {
UP: 38,
DOWN: 40,
};
if (event && keyDefinitions) {
for (var k in keys) {
if (keys.hasOwnProperty(k) && keys[k] === event.keyCode) {
key = k;
}
}
if (!key) return;
var navigationFunction = keyDefinitions[key];
if (!navigationFunction) {
console.log('Undefined key: ' + key);
return;
}
event.preventDefault();
scope.$apply(navigationFunction());
return;
}
return;
});
}
}
}
})();