AngularJS表中的键盘导航

时间:2014-05-02 14:41:58

标签: javascript angularjs

我试图将Windows(德尔福VCL)制作的特殊表格/网格表格移植到Angular应用程序。

可以在此处测试角度应用的简化版本:jsFiddle demo

用户可以根据需要添加任意数量的行,如jsFiddle中所示。

问题是:是否可以使用Angular指令或其他一些Angular魔法解决以下问题?

  1. 按下回车键时跳转到下一个单元格(右侧单元格或新行)。
  2. 直接跳到箭头下方的牢房。
  3. 在箭头上方直接跳到上方。
  4. 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());
      }
    
    }
    

2 个答案:

答案 0 :(得分:7)

我想出来了。 This Plunk将导航输入键和所有箭头键(向上,向下,向左,向右)。谢谢@Armen指出我正确的方向。

<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();
        }
      }
    }
  };
})

我从不同来源做过som复制/粘贴。需要重构。

答案 1 :(得分:2)

看看this 普拉克。 注意属性&#39;可导航&#39;在桌子上添加。 这不是您问题的完整解决方案(仅添加&#34;输入&#34;按钮行为),但只是想知道如何优雅地向表输入添加导航功能。 请注意,这里加载了jquery! checkout this doc,以更好地理解角度中的jquery用法。来自文档的引文:

  

jqLit​​e是一个微小的API兼容的jQuery子集,它允许Angular以跨浏览器兼容的方式操作DOM。 jqLit​​e仅实现最常用的功能,目标是占用空间非常小。