简体   繁体   English

AngularJS:如何处理路由控制器中的键盘快捷键?

[英]AngularJS: How to handle keyboard shortcuts in routing controllers?

How do you implement page-specific keyboard shortcuts in an AngularJS 1.5 app that uses routing ? 如何在使用路由的AngularJS 1.5应用程序中实现特定于页面的键盘快捷方式

This is what I would like to achieve: 这是我要实现的目标:

index.html: index.html:

<!doctype html>
<html data-ng-app="myApp">
<body data-ng-keydown="onKeyDown($event)">
    ...
    <div data-ng-view></div>
    ...
</body>
</html>

As I understand, you need to handle key-down events on the &lt;body&gt; 据我了解,您需要处理&lt;body&gt;上的按键事件&lt;body&gt; tag, if you don't have elements in the scope that are focused (input fields for example, I don't have those). 标签,如果您在范围内没有重点关注的元素(例如,输入字段,则没有这些元素)。

app.js: app.js:

var myApp = angular.module('myApp', ['ngRoute', 'myControllers']);

myApp.config(['$routeProvider', function ($routeProvider) {
    $routeProvider
        .when('/', {
            templateUrl: 'pages/home.html',
            controller: 'HomeCtrl'
        })
        .when('/create', {
            templateUrl: 'pages/create.html',
            controller: 'CreateCtrl'
        });
}]);

controllers.js: controllers.js:

var myControllers = angular.module('myControllers', []);

myControllers.controller('HomeCtrl', ['$scope', function ($scope) {

    $scope.closeLandingPagePopUp = function () {
        ...
    };

    $scope.onKeyDown = function ($event) {
        switch ($event.keyCode) {
            case 27: // [Esc]
                $scope.closeLandingPagePopUp();
                break;
            ...
        }
    };
}]);

myControllers.controller('CreateCtrl', ['$scope', function ($scope) {

    $scope.cancelCreation = function () {
        ...
    };

    $scope.onKeyDown = function ($event) {
        switch ($event.keyCode) {
            case 27: // [Esc]
                $scope.cancelCreation();
                break;
            ...
        }
    };
}]);

So on both pages the [Esc] key should be handled differently. 因此,在两个页面上,[Esc]键应以不同的方式处理。

Of course the HTML attribute data-ng-keydown="onKeyDown($event)" doesn't work, because it's outside the controllers' scopes. 当然,HTML属性data-ng-keydown="onKeyDown($event)"不起作用,因为它超出了控制器的范围。

Is there a way to do this while still keeping all page specific code within their respective controller? 有办法做到这一点,同时仍将所有页面特定的代码保留在各自的控制器中吗?

Global Keydown Directive 全局Keydown指令

To get events outside of a directive, bind the event handler to $document . 要获取指令外的事件,请将事件处理程序绑定到$document

angular.module('myApp').directive("globalKeydown", 
  function($document) {
    return function linkFn(scope,elem,attrs) {
        var handlerUnbind = $document.on("keydown", function(e) {
            scope.$eval(attrs.globalKeydown, {$event: e});
            scope.$apply();
        });
        scope.$on('$destroy', function() {
             handlerUnbind();
        })
    }
});

This example directive puts a keydown event handler on the $document that invokes the expression defined by the global-event attribute. 此示例指令将keydown事件处理程序放在$document上,该处理程序调用由global-event属性定义的表达式。 The event is as exposed as $event . 该事件与$event一样公开。

Example Usage 用法示例

<div ng-app="myApp">
   <p>Click this window and press any key</p>
   <p global-keydown='keycode=($event.code)'>
      Global keydown = {{keycode}}
   </p>
</div>

The DEMO on JSFiddle . JSFiddle上DEMO

For more information on $event , see AngularJS Developer Guide -- $event . 有关$event更多信息,请参见《 AngularJS开发人员指南-$ event》

georgeawg's answer was inspiring, but I ended up with this implementation: georgeawg的答案令人鼓舞,但我最终实现了该实现:

myControllers.controller('HomeCtrl', ['$scope', '$document', function ($scope, $document) {

    var handleKeyDown = function(event) {
        switch (event.keyCode) {
            case 27: // [Esc]
                $scope.closeLandingPagePopUp();
                break;
            ...
        }
        $scope.$apply();
    };
    $document.on('keydown', handleKeyDown);

    $scope.$on('$destroy', function() {
        $document.unbind('keydown', handleKeyDown);
    });
}]);

There is actually nothing to do within the HTML parts. 实际上,HTML部分中没有任何事情要做。

Explanation: 说明:

  1. Every controller has a handleKeyDown(event) function that implements the shortcuts 每个控制器都有一个实现快捷方式的handleKeyDown(event)函数
  2. $document.on('keydown', handleKeyDown) binds the handler function to global keydown events when the controller is initialized. 初始化控制器时$document.on('keydown', handleKeyDown)将处理函数绑定到全局keydown事件。 $document is Angular's jQuery wrapper. $ document是Angular的jQuery包装器。
  3. Unbind the handler when the controller get's destroyed 销毁控制器后解除绑定处理程序
  4. Use $scope.$apply() to let Angular know when data has changed and the view needs to be refreshed 使用$scope.$apply()让Angular知道何时数据已更改并且视图需要刷新

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM