什么是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的替代版本
略短的答案只是看下面的解决scheme3。 如果你想知道更多的select,你可以阅读整个事情。
我同意jmagnusson。 但我相信有更清洁的解决scheme。 而不是绑定与指令中的函数的键,你应该能够像在定义一个configuration文件的HTML绑定他们,热键应该是上下文。
-
下面是一个使用自定义指令鼠标陷阱的版本。 (我不是这个小提琴的作者。)
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>
该解决scheme要求您包含可帮助您定义热键的库mousetrap.js。
-
如果你想避免麻烦开发自己的自定义指令,你可以看看这个lib:
https://github.com/drahak/angular-hotkeys
和这个
https://github.com/chieffancypants/angular-hotkeys
第二个提供更多的function和灵活性,即为您的应用程序自动生成的热键备忘单。
更新 :解决scheme3不再适用于Angular UI。
-
除了上面的解决scheme,还有另一个由锐锐团队完成的实现。 但缺点是解决scheme取决于JQuery lib,这不是angular度社区的趋势。 (Angular社区尝试只使用angularjs附带的jqLite,远离过度的依赖关系。)这里是链接
用法是这样的:
在你的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>