AngularJS ng-keydown 指令仅适用于 <input> 上下文?

Posted

技术标签:

【中文标题】AngularJS ng-keydown 指令仅适用于 <input> 上下文?【英文标题】:AngularJS ng-keydown directive only working for <input> context? 【发布时间】: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 或本机脚本尝试同样的事情有同样的问题。可以将事件绑定到文档并测试该目标不是输入。不确定您的用例是什么 【参考方案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://***.com/a/1718035/80264

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

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

【讨论】:

非常好的信息。唯一的问题是当它获得焦点时,至少在 FireFox 中,我会在元素周围得到一个大的红色边框。 我认为这是因为firefox默认处理html表单验证的方式?看看这是否有帮助:***.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);
    

【讨论】:

以上是关于AngularJS ng-keydown 指令仅适用于 <input> 上下文?的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS 指令

05AngularJS 指令

AngularJs 指令

AngularJS 指令实践指南

JavaScript强化教程——AngularJS 指令

AngularJS中的指令