什么是AngularJS创build全局键盘快捷键的方法?

我想我应该使用指令,但是将伪指令添加到body看起来很奇怪,但在文档上侦听事件。

什么是正确的方法来做到这一点?

更新:发现AngularJS用户界面,看到他们的keypress指令的实现。

以下是我如何用jQuery做到这一点 – 我认为有一个更好的方法。

 var app = angular.module('angularjs-starter', []); app.directive('shortcut', function() { return { restrict: 'E', replace: true, scope: true, link: function postLink(scope, iElement, iAttrs){ jQuery(document).on('keypress', function(e){ scope.$apply(scope.keyPressed(e)); }); } }; }); app.controller('MainCtrl', function($scope) { $scope.name = 'World'; $scope.keyCode = ""; $scope.keyPressed = function(e) { $scope.keyCode = e.which; }; }); 
 <body ng-controller="MainCtrl"> <shortcut></shortcut> <h1>View keys pressed</h1> {{keyCode}} </body> 

Plunker演示

我会说一个更合适的方式(或“angular度的方式”)将其添加到指令。 下面是一个简单的keypress-events (只需将keypress-events属性添加到<body> ):

 angular.module('myDirectives', []).directive('keypressEvents', [ '$document', '$rootScope', function($document, $rootScope) { return { restrict: 'A', link: function() { $document.bind('keypress', function(e) { console.log('Got keypress:', e.which); $rootScope.$broadcast('keypress', e); $rootScope.$broadcast('keypress:' + e.which, e); }); } }; } ]); 

在你的指令中,你可以简单地做这样的事情:

 module.directive('myDirective', [ function() { return { restrict: 'E', link: function(scope, el, attrs) { scope.keyPressed = 'no press :('; // For listening to a keypress event with a specific code scope.$on('keypress:13', function(onEvent, keypressEvent) { scope.keyPressed = 'Enter'; }); // For listening to all keypress events scope.$on('keypress', function(onEvent, keypressEvent) { if (keypress.which === 120) { scope.keyPressed = 'x'; } else { scope.keyPressed = 'Keycode: ' + keypressEvent.which; } }); }, template: '<h1>{{keyPressed}}</h1>' }; } ]); 

使用$document.bind

 function FooCtrl($scope, $document) { ... $document.bind("keypress", function(event) { console.debug(event) }); ... } 

我不能保证它,但我已经开始看看AngularHotkeys.js:

http://chieffancypants.github.io/angular-hotkeys/

一旦我有了我的牙齿,将更多的信息更新。

更新1:哦,有一个nuget包:angular-hotkeys

更新2:实际上非常容易使用,只需在您的路由器中设置绑定,或者在您的控制器中设置绑定:

 hotkeys.add('n', 'Create a new Category', $scope.showCreateView); hotkeys.add('e', 'Edit the selected Category', $scope.showEditView); hotkeys.add('d', 'Delete the selected Category', $scope.remove); 

这里是一个键盘快捷方式的AngularJS服务的例子: http : //jsfiddle.net/firehist/nzUBg/

它可以像这样使用:

 function MyController($scope, $timeout, keyboardManager) { // Bind ctrl+shift+d keyboardManager.bind('ctrl+shift+d', function() { console.log('Callback ctrl+shift+d'); }); } 

更新:我现在正在使用angular-hotkeys 。

作为指令

这本质上是如何在Angular文档代码中完成的,即按/开始search。

 angular .module("app", []) .directive("keyboard", keyboard); function keyboard($document) { return { link: function(scope, element, attrs) { $document.on("keydown", function(event) { // if keycode... event.stopPropagation(); event.preventDefault(); scope.$apply(function() { // update scope... }); } }; } 

使用键盘指令来使用Plunk

http://plnkr.co/edit/C61Gnn?p=preview


作为服务

将该指令转换为服务非常简单。 唯一真正的区别是范围没有暴露在服务上。 要触发摘要,可以引入$rootScope或使用$timeout

 function Keyboard($document, $timeout, keyCodes) { var _this = this; this.keyHandlers = {}; $document.on("keydown", function(event) { var keyDown = _this.keyHandlers[event.keyCode]; if (keyDown) { event.preventDefault(); $timeout(function() { keyDown.callback(); }); } }); this.on = function(keyName, callback) { var keyCode = keyCodes[keyName]; this.keyHandlers[keyCode] = { callback: callback }; return this; }; } 

您现在可以使用keyboard.on()方法在您的控制器中注册callback。

 function MainController(keyboard) { keyboard .on("ENTER", function() { // do something... }) .on("DELETE", function() { // do something... }) .on("SHIFT", function() { // do something... }) .on("INSERT", function() { // do something... }); } 

使用服务的Plunk的替代版本

http://plnkr.co/edit/z9edu5?p=preview

略短的答案只是看下面的解决scheme3。 如果你想知道更多的select,你可以阅读整个事情。

我同意jmagnusson。 但我相信有更清洁的解决scheme。 而不是绑定与指令中的函数的键,你应该能够像在定义一个configuration文件的HTML绑定他们,热键应该是上下文。

  1. 下面是一个使用自定义指令鼠标陷阱的版本。 (我不是这个小提琴的作者。)

     var app = angular.module('keyExample', []); app.directive('keybinding', function () { return { restrict: 'E', scope: { invoke: '&' }, link: function (scope, el, attr) { Mousetrap.bind(attr.on, scope.invoke); } }; }); app.controller('RootController', function ($scope) { $scope.gotoInbox = function () { alert('Goto Inbox'); }; }); app.controller('ChildController', function ($scope) { $scope.gotoLabel = function (label) { alert('Goto Label: ' + label); }; }); 

    你需要包含mousetrap.js,你可以像下面这样使用它:

     <div ng-app="keyExample"> <div ng-controller="RootController"> <keybinding on="gi" invoke="gotoInbox()" /> <div ng-controller="ChildController"> <keybinding on="gl" invoke="gotoLabel('Sent')" /> </div> </div> <div>Click in here to gain focus and then try the following key strokes</div> <ul> <li>"gi" to show a "Goto Inbox" alert</li> <li>"gl" to show a "Goto Label" alert</li> </ul> </div> 

    http://jsfiddle.net/BM2gG/3/

    该解决scheme要求您包含可帮助您定义热键的库mousetrap.js。

  2. 如果你想避免麻烦开发自己的自定义指令,你可以看看这个lib:

    https://github.com/drahak/angular-hotkeys

    和这个

    https://github.com/chieffancypants/angular-hotkeys

    第二个提供更多的function和灵活性,即为您的应用程序自动生成的热键备忘单。

更新 :解决scheme3不再适用于Angular UI。

  1. 除了上面的解决scheme,还有另一个由锐锐团队完成的实现。 但缺点是解决scheme取决于JQuery lib,这不是angular度社区的趋势。 (Angular社区尝试只使用angularjs附带的jqLit​​e,远离过度的依赖关系。)这里是链接

    http://angular-ui.github.io/ui-utils/#/keypress

用法是这样的:

在你的html中,使用ui-keydown属性来绑定键和函数。

 <div class="modal-inner" ui-keydown="{ esc: 'cancelModal()', tab: 'tabWatch($event)', enter: 'initOrSetModel()' }"> 

在您的指令中,将这些函数添加到您的作用域中。

 app.directive('yourDirective', function () { return { restrict: 'E', templateUrl: 'your-html-template-address.html' link: function(){ scope.cancelModal() = function (){ console.log('cancel modal'); }; scope.tabWatch() = function (){ console.log('tabWatch'); }; scope.initOrSetModel() = function (){ console.log('init or set model'); }; } }; }); 

玩过所有的解决scheme后,我会推荐一个由Angular UI团队实施的解决scheme3,它避免了我遇到的许多小奇怪的问题。

我为快捷方式提供了服务。

看起来像:

 angular.module('myApp.services.shortcuts', []) .factory('Shortcuts', function($rootScope) { var service = {}; service.trigger = function(keycode, items, element) { // write the shortcuts logic here... } return service; }) 

我把它注入控制器:

 angular.module('myApp.controllers.mainCtrl', []) .controller('mainCtrl', function($scope, $element, $document, Shortcuts) { // whatever blah blah $document.on('keydown', function(){ // skip if it focused in input tag if(event.target.tagName !== "INPUT") { Shortcuts.trigger(event.which, $scope.items, $element); } }) }) 

它的工作,但你可能会注意到,我注入$元和$文档到控制器。

这是一个糟糕的控制器惯例,违反了“不要在控制器的约定中访问$元素”。

我应该把它写入指令,然后使用'ngKeydown'和$ event触发服务。

但是我觉得这个服务很好,我会尽快重做控制器。


更新:

看起来像“ng-keydown”只能用于input标签。

所以我只写一个指令并注入$ document:

 angular.module('myApp.controllers.mainCtrl', []) .directive('keyboard', function($scope, $document, Shortcuts) { // whatever blah blah return { link: function(scope, element, attrs) { scope.items = ....;// something not important $document.on('keydown', function(){ // skip if it focused in input tag if(event.target.tagName !== "INPUT") { Shortcuts.trigger(event.which, scope.items, element); } }) } } }) 

好多了

从behid ng-newsletter.com网站上查看这个例子 ; 检查他们的教程创build一个2048年的游戏,它有一些很好的代码使用键盘事件的服务。

下面让我们把你所有的快捷方式逻辑写在你的控制器中,这个指令将会处理所有的事情。

指示

 .directive('shortcuts', ['$document', '$rootScope', function($document, $rootScope) { $rootScope.shortcuts = []; $document.on('keydown', function(e) { // Skip if it focused in input tag. if (event.target.tagName !== "INPUT") { $rootScope.shortcuts.forEach(function(eventHandler) { // Skip if it focused in input tag. if (event.target.tagName !== 'INPUT' && eventHandler) eventHandler(e.originalEvent, e) }); } }) return { restrict: 'A', scope: { 'shortcuts': '&' }, link: function(scope, element, attrs) { $rootScope.shortcuts.push(scope.shortcuts()); } }; }]) 

调节器

  $scope.keyUp = function(key) { // H. if (72 == key.keyCode) $scope.toggleHelp(); }; 

HTML

 <div shortcuts="keyUp"> <!-- Stuff --> </div> 

你可以尝试这个库,它使得它很容易pipe理热键,它会自动绑定和解绑键在你浏览应用程序

angular热键

我不知道这是一个真正的angular度,但我做了什么

 $(document).on('keydown', function(e) { $('.button[data-key=' + String.fromCharCode(e.which) + ']').click(); }); <div class="button" data-key="1" ng-click="clickHandler($event)"> ButtonLabel </div>