【问题标题】:Navigate the UI using keyboard使用键盘导航 UI
【发布时间】:2013-05-31 14:44:28
【问题描述】:

考虑以下标记 -

<ul id="list">
    <li class="list-item" tabindex="0">test 1</li>
    <li class="list-item" tabindex="1">test 2</li>
    <li class="list-item" tabindex="2">test 3</li>
    <li class="list-item" tabindex="3">test 4</li>
    <li class="list-item" tabindex="4">test 5</li>
    <li class="list-item" tabindex="5">test 6</li>
    <li class="list-item" tabindex="6">test 7</li>
</ul>

还有这段 jQuery 代码 -

$(".list-item").bind({
    keydown: function(e) {
        var key = e.keyCode;
        var target = $(e.currentTarget);

        switch(key) {
            case 38: // arrow up
                target.prev().focus();
                break;
            case 40: // arrow down
                target.next().focus();
                break;
        }
    },

    focusin: function(e) {
        $(e.currentTarget).addClass("selected");
    },

    focusout: function(e) {
        $(e.currentTarget).removeClass("selected");
    }
});
$("li").first().focus();

如何以角度移植此代码?到目前为止我有这个 -

 <li class="list-item" ng-repeat="item in items" tabindex="{{item.tabIndex}}">
                        {{item.name}}
                    </li>

如何进行角度绑定?

【问题讨论】:

标签: angularjs


【解决方案1】:

我认为最好的方法是使用tabindex 来定位焦点元素。试试这样的;

<li class="list-item" ng-repeat="item in items" 
    tabindex="{{item.tabIndex}}"
    ng-class="item.selected"
    ng-keydown="onKeydown(item, $event)" ng-focus="onFocus(item)">{{item.name}}
</li>

然后在您的控制器中,您需要 Keydown 处理程序;

var KeyCodes = {
    BACKSPACE : 8,
    TABKEY : 9,
    RETURNKEY : 13,
    ESCAPE : 27,
    SPACEBAR : 32,
    LEFTARROW : 37,
    UPARROW : 38,
    RIGHTARROW : 39,
    DOWNARROW : 40,
};

$scope.onKeydown = function(item, $event) {
        var e = $event;
        var $target = $(e.target);
        var nextTab;
        switch (e.keyCode) {
            case KeyCodes.ESCAPE:
                $target.blur();
                break;
            case KeyCodes.UPARROW:
                nextTab = - 1;
                break;
            case KeyCodes.RETURNKEY: e.preventDefault();
            case KeyCodes.DOWNARROW:
                nextTab = 1;
                break;
        }
        if (nextTab != undefined) {
            // do this outside the current $digest cycle
            // focus the next element by tabindex
           $timeout(() => $('[tabindex=' + (parseInt($target.attr("tabindex")) + nextTab) + ']').focus());
        }
};

还有一个保持简单的焦点处理程序;

$scope.onFocus = function(item, $event) {
    // clear all other items
    angular.forEach(items, function(item) {
        item.selected = undefined;
    });

    // select this one
    item.selected = "selected";
};

这不是我的想法,以防万一有人像我一样遇到这个问题。

【讨论】:

    【解决方案2】:

    您还可以创建如下所示的角度指令:

    claimApp.directive('keyNavigation', function ($timeout) {
        return function (scope, element, attrs) {
            element.bind("keydown keypress", function (event) {
                if (event.which === 38) {
                    var target = $(event.target).prev();
                    $(target).trigger('focus');
                }
                if (event.which === 40) {
                    var target = $(event.target).next();
                    $(target).trigger('focus');
                }
            });
        };
    });
    

    然后像这样在你的 HTML 中使用它:

    <li class="list-item" ng-repeat="item in items" key-navigation>
                        {{item.name}}
                    </li>
    

    【讨论】:

    • 不建议在指令中使用 jquery。尝试使用 angular.element 本身更改它。
    【解决方案3】:

    这个问题在被问到之前几个月就得到了回答,并且在Plunker 上有一个实时工作示例。

    var app = angular.module('test', []);
    
    app.controller('testCtrl',function ($scope, $window) {
    $scope.console = $window.console;
    
    $scope.records = [];
    for (var i = 1; i <= 9; i++) {
    $scope.records.push({ id: i, navIndex: i, name: 'record ' + i});
    }
    
    $scope.focusIndex = 3;
    
    $scope.open = function ( index ) {
    var record = $scope.shownRecords[ index ]
    console.log('opening : ', record );
     };
    
    $scope.keys = [];
    $scope.keys.push({ code: 13, action: function() { $scope.open( $scope.focusIndex ); }});
    $scope.keys.push({ code: 38, action: function() { $scope.focusIndex--; }});
    $scope.keys.push({ code: 40, action: function() { $scope.focusIndex++; }});
    

    在此线程前几周提出的类似问题的链接是Stackoverflow

    【讨论】:

      【解决方案4】:

      没有 jQuery 的指令

      .directive('arrow', function ($timeout) {
          return function (scope, element, attrs) {
              element.bind("keydown keypress", function (event) {
                  if (event.which === 38) {
                    var prevNode = element[0].previousElementSibling;
                    var prev = angular.element(prevNode);
                    prev[0].focus();
                  }
                  if (event.which === 40) {
                      var target = element.next();
                      target[0].focus();
                  }
              });
          };
      });
      

      html中的用法

      <tr arrow>
        <td>test 1</td>                       
      </tr>
      <tr arrow>
        <td>test 2</td>                       
      </tr>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-07
        • 2011-03-29
        • 1970-01-01
        • 1970-01-01
        • 2017-06-11
        相关资源
        最近更新 更多