What is AngularJS way to create global keyboard shortcuts?

后端 未结 12 2081
一整个雨季
一整个雨季 2020-11-30 22:04

I suppose that I should use directive, but it seems strange to add directive to body, but listen events on document.

What is a proper way to do this?

UPDATE:

相关标签:
12条回答
  • 2020-11-30 22:41

    Check this example from the guys behid ng-newsletter.com; check their tutorial on creating a 2048 game, it has some nice code using a service for keyboard events.

    0 讨论(0)
  • 2020-11-30 22:43

    The following let's you write all your shortcut logic in your controller and the directive will take care of everything else.

    Directive

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

    Controller

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

    Html

    <div shortcuts="keyUp">
        <!-- Stuff -->
    </div>
    
    0 讨论(0)
  • 2020-11-30 22:45

    I can't vouch for it just yet but I've started taking a look at AngularHotkeys.js:

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

    Will update with more info once I've got my teeth into it.

    Update 1: Oh there's a nuget package: angular-hotkeys

    Update 2: actually very easy to use, just set up your binding either in your route or as I'm doing, in your controller:

    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);
    
    0 讨论(0)
  • 2020-11-30 22:46

    Here's an example of an AngularJS service for keyboard shortcuts: http://jsfiddle.net/firehist/nzUBg/

    It can then be used like this:

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

    Update: I'm now using angular-hotkeys instead.

    0 讨论(0)
  • 2020-11-30 22:46

    you can try this library it made it very easy to manage hot keys, it automatically binds and unbinds keys as you navigate the app

    angular-hotkeys

    0 讨论(0)
  • 2020-11-30 22:52

    As a Directive

    This is essentially how it is done in the Angular documentation code, i.e. pressing / to start searching.

    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 using a keyboard directive

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


    As a Service

    Converting that directive into a service is real easy. The only real difference is that the scope is not exposed on the service. To trigger a digest, you can bring in the $rootScope or use a $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;
      };
    }
    

    You can now register callbacks in your controller using the keyboard.on() method.

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

    Alternate version of Plunk using a service

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

    0 讨论(0)
提交回复
热议问题