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

时间:2016-03-28 16:16:47

标签: javascript angularjs angularjs-directive angular-ui-router keyboard-shortcuts

如何在使用路由的AngularJS 1.5应用中实现特定于页面的键盘快捷键

这就是我想要实现的目标:

的index.html:

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

据我了解,您需要处理&lt;body&gt;标记上的关键事件,如果您没有关注范围内的元素(例如输入字段,我不会&#39;有那些)。

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:

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;
            ...
        }
    };
}]);

因此,在两个页面上,[Esc]键的处理方式应该不同。

当然,HTML属性data-ng-keydown="onKeyDown($event)"不起作用,因为它在控制器之外&#39;作用域。

有没有办法在将所有页面特定代码保留在各自的控制器中时执行此操作?

2 个答案:

答案 0 :(得分:1)

Global Keydown Directive

要获取指令之外的事件,请将事件处理程序绑定到$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();
        })
    }
});

此示例指令在keydown上放置一个$document事件处理程序,用于调用global-event属性定义的表达式。该事件与$event一样公开。

使用示例

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

DEMO on JSFiddle

有关$event的详细信息,请参阅AngularJS Developer Guide -- $event

答案 1 :(得分:1)

georgeawg's answer鼓舞人心,但我最终得到了这个实现:

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);
    });
}]);

HTML部分实际上无关紧要。

<强>解释

  1. 每个控制器都有一个实现快捷方式的handleKeyDown(event)功能
  2. $document.on('keydown', handleKeyDown)在初始化控制器时将处理程序函数绑定到全局keydown事件。 $document是Angular的jQuery包装器。
  3. 在控制器被销毁时取消绑定处理程序
  4. 使用$scope.$apply()让Angular知道数据何时发生变化并且需要刷新视图