【问题标题】:AngularJS ng-keydown directive only working for <input> context?AngularJS ng-keydown 指令仅适用于 <input> 上下文?
【发布时间】:2013-03-20 05:52:20
【问题描述】:

我对 AngularJS 还是很陌生,但到目前为止我觉得它很合我的胃口。对于我当前的项目,我需要热键功能,并且很高兴看到它从 1.1.2 版本开始就受到支持。

ng-keydown 指令 (http://code.angularjs.org/1.1.3/docs/api/ng.directive:ngKeydown) 对输入类型按预期工作,但对任何其他上下文(如 div 等)都失败了。考虑到文档另有说明,这似乎很奇怪。

这里是一个最小的例子(http://jsfiddle.net/TdXWW/12/),分别是工作和不工作:

<input ng-keydown="keypress($event)">
<div ng-keydown="keypress($event)">

注意:我知道这可以用普通的 jQuery (http://www.mkyong.com/jquery/how-to-check-if-an-enter-key-is-pressed-with-jquery/) 处理,但我更喜欢了解如何在 AngularJS 中处理它。

【问题讨论】:

  • 不是contenteditable 的div 在单击时不会触发焦点,因此没有活动元素可将keypress 绑定到。使用 jQuery 或本机脚本尝试同样的事情有同样的问题。可以将事件绑定到文档并测试该目标不是输入。不确定您的用例是什么

标签: angularjs hotkeys


【解决方案1】:

charlietfl 的评论清除了一切,并将事件绑定到 $(document) 按预期工作!带走的信息:AngularJS 文档并不详尽,即需要背景知识。

【讨论】:

    【解决方案2】:

    谢谢!总结一下,我通过将 $document 注入到我的指令中来完成这个工作,然后:

    MyApp.directive('myDirective', function($document) {
    return {
    ...
     $document.keydown(function(e){
       console.log(e)
     })
    }
    

    【讨论】:

    • 我需要做 $($document).keydown(... 才能让它工作。我猜 jQuery-lite 没有 keydown 功能?
    • @Crashthatch 为 jQuery-lite 使用 .on('keydown')
    【解决方案3】:

    我遇到了同样的问题,并且能够按照此评论中提供的这个简单提示解决它:https://stackoverflow.com/a/1718035/80264

    您需要给 div 一个 tabindex 以便它可以接收焦点。

    <div id="testdiv" tabindex="0"></div>
    

    【讨论】:

    • 非常好的信息。唯一的问题是当它获得焦点时,至少在 FireFox 中,我会在元素周围得到一个大的红色边框。
    • 我认为这是因为firefox默认处理html表单验证的方式?看看这是否有帮助:stackoverflow.com/questions/3809146/…
    • 感谢您的链接。最后,我将 ng-keydown 和 ng-keyup 添加到 body 元素中,然后在 body 控制器中调用函数。然后这些设置一个变量,但也可以广播到其他控制器。非常适合我的需求(使用 shift 选择数据)。感谢您的回复。
    • 世界上没有足够的赞成票。这让我疯狂了一个小时。
    【解决方案4】:

    这就是我最终得到它的方式。

    ng-app 添加到html 元素,将ng-keyupng-keydown 添加到body 元素:

    <html ng-app="myApp" ng-controller="MainCtrl">
    .....
    <body ng-keydown="keyPress($event);" ng-keyup="keyRelease($event);">
    

    然后我的控制器中的函数处理事件调用 event.which 以获取关键代码(在我的实现中,我为 rootScope 设置了一个 var,但您也可以广播到其他控制器)

    $scope.keyPress = function(eve) {
        if (eve.which === 16) { // shift
            // $rootScope.$broadcast('doShift');
            $rootScope.shiftOn = true;
        };
    };
    

    【讨论】:

    • 如果您使用多个子模板并且只有一个主体,这并不令人惊讶。我更喜欢自定义指令
    【解决方案5】:
    angular.module('app').directive('executeOnEnter', function () {
        return {
            restrict: 'A',
            link: function (scope, el, attrs, $rootScope) {                      
                $('body').on('keypress', function (evt) {
                    if (evt.keyCode === 13) {
                        el.trigger('click', function () {
                        });
                    }            
                })
    
            },
            controller: function ($rootScope) {
                function removeEvent() {
                    $("body").unbind("keypress");
                }
                $rootScope.$on('$stateChangeStart', removeEvent);
            }
        }
    })
    

    【讨论】:

    • 您正在绑定正文上的按键。因此,如果您的视图发生更改或您不需要绑定到其他视图时,绑定会继续 word 事件。
    • 如果您对此感到担忧,我编辑了答案。当然,这可能会删除你之前附加到身体的东西(在按键上),所以你可能需要注意这一点。
    【解决方案6】:

    它对我来说很好,只需添加 tabindex 属性。确保 ng-keydown 包含正确的 angularjs 表达式

        <div ng-keydown="keypress($event)" tabindex="0">
    
        $scope.keypress = function(ev) {
            console.log('keyprez', ev);
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-09
      • 2014-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多