Keyboard navigation in an AngularJS table

I am trying to transfer a special table / grid form made in Windows (Delphi VCL) to an Angular application.

Here you can test a simplified version of the Angular application: jsFiddle demo .

The user can add as many rows as he wants, as shown in jsFiddle.

The question arises: is it possible to solve the following using the Angular directive or some other Angular magic?

  • go to the next cell (the cell on the right or a new line) when you press the enter key.
  • Go to the cell directly below the down arrow.
  • Go to the cell directly above the up arrow.

HTML:

<tbody> <tr ng-repeat="p in persons"> <td> <input ng-model="p.name"> </td> <td> <input ng-model="p.age"> </td> <td> <button ng-click="add($index)">Add new person</button> </td> </tr> </tbody> 

JS:

 function TestingCtrl($scope) { $scope.persons = [{ name: 'Alice', age: 20 }, { name: 'Bob', age: 30 }]; $scope.add = function(index) { var newPerson = function() { return { name: '', age: '' }; }; $scope.persons.splice(index + 1, 0, new newPerson()); } } 
+1
source share
2 answers

I get it. This tablet will move along the enter key and to all the arrow keys (up, down, left, right). Thanks to @Armen for pointing me in the right direction.

 <div ng-app="myApp"> <div ng-controller="TestingCtrl"> <table navigatable> <thead> <tr> <th>Name</th> <th>Age</th> <th></th> </tr> </thead> <tbody> <tr ng-repeat="p in persons"> <td> <input type="text" ng-model="p.name"> </td> <td> <input type="text" ng-model="p.age"> </td> <td> <button ng-click="add($index)">Add new person</button> </td> </tr> </tbody> </table> </div> 

 angular.module("myApp", []) .controller("TestingCtrl", ["$scope", function TestingCtrl($scope) { $scope.persons = [{ name: 'Alice', age: 20 }, { name: 'Bob', age: 30 }]; $scope.add = function(index) { var newPerson = function() { return { name: '', age: '' }; }; $scope.persons.splice(index + 1, 0, new newPerson()); } } ]) .directive('navigatable', function() { return function(scope, element, attr) { element.on('keypress.mynavigation', 'input[type="text"]', handleNavigation); function handleNavigation(e) { var arrow = {left: 37, up: 38, right: 39, down: 40}; // select all on focus element.find('input').keydown(function(e) { // shortcut for key other than arrow keys if ($.inArray(e.which, [arrow.left, arrow.up, arrow.right, arrow.down]) < 0) { return; } var input = e.target; var td = $(e.target).closest('td'); var moveTo = null; switch (e.which) { case arrow.left: { if (input.selectionStart == 0) { moveTo = td.prev('td:has(input,textarea)'); } break; } case arrow.right: { if (input.selectionEnd == input.value.length) { moveTo = td.next('td:has(input,textarea)'); } break; } case arrow.up: case arrow.down: { var tr = td.closest('tr'); var pos = td[0].cellIndex; var moveToRow = null; if (e.which == arrow.down) { moveToRow = tr.next('tr'); } else if (e.which == arrow.up) { moveToRow = tr.prev('tr'); } if (moveToRow.length) { moveTo = $(moveToRow[0].cells[pos]); } break; } } if (moveTo && moveTo.length) { e.preventDefault(); moveTo.find('input,textarea').each(function(i, input) { input.focus(); input.select(); }); } }); var key = e.keyCode ? e.keyCode : e.which; if (key === 13) { var focusedElement = $(e.target); var nextElement = focusedElement.parent().next(); if (nextElement.find('input').length > 0) { nextElement.find('input').focus(); } else { nextElement = nextElement.parent().next().find('input').first(); nextElement.focus(); } } } }; }) 

I made som copy / paste from different sources. Need refactoring.

+7
source

See it ring. Note the "navigatable" attribute added to the table. This is not a complete solution to your problem (only the "enter" button behavior has been added), but just an idea of ​​how you can elegantly add navigation functionality to your table tabs. Please note that jquery is loaded here! checkout this doc to better understand the use of jquery in angular. Quoting from the documentation:

jqLite is a tiny API-compatible jQuery subset that allows Angular to manipulate the DOM in a cross-browser fashion. jqLite implements only the most commonly used functions in order to have a very small area.

+2
source

Source: https://habr.com/ru/post/1204328/


All Articles