77

ディレクティブを使うべきだと思うのですが、ボディにディレクティブを追加するのは奇妙に思えますが、ドキュメントのイベントをリッスンします。

これを行う適切な方法は何ですか?

更新: AngularJS UI を見つけて、keypress ディレクティブの実現を見ました。

4

12 に答える 12

70

より適切な方法 (または「Angular の方法」) は、それをディレクティブに追加することです。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>'
    };
  }
]);
于 2013-10-16T19:33:46.950 に答える
27

使用$document.bind:

function FooCtrl($scope, $document) {
    ...
    $document.bind("keypress", function(event) {
        console.debug(event)
    });
    ...
}
于 2013-10-06T17:57:24.713 に答える
20

まだ保証することはできませんが、AngularHotkeys.js を調べ始めました。

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

慣れてきたら、さらに情報を更新します。

更新 1: ナゲット パッケージがあります: 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);
于 2014-04-22T11:10:38.210 に答える
10

これが私が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>

プランカーのデモ

于 2013-02-23T19:58:38.960 に答える
10

キーボード ショートカット用の 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を使用しています。

于 2013-11-06T12:22:32.177 に答える
7

指令として

これは基本的に、Angular ドキュメント コードで行われる方法です。つまり、 を押し/て検索を開始します。

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()

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

于 2014-09-14T11:09:33.360 に答える
1

ショートカットのサービスを作りました。

次のようになります。

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

これは機能しますが、コントローラーに $element と $document を挿入していることに気付くかもしれません。

これはコントローラーの悪い慣行であり、「コントローラーの $element に決してアクセスしないでください」という規則に違反しています。

それをディレクティブに入れてから、「ngKeydown」と $event を使用してサービスをトリガーする必要があります。

でもサービスはいいと思うし、もっと早くコントローラーを作り直そう。


更新しました:

「ng-keydown」は入力タグでのみ機能するようです。

したがって、ディレクティブを記述して $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);
         }
       })
     }
   }
  })

それは良いです。

于 2014-01-18T08:24:10.197 に答える
0

それが本当の角度のある方法かどうかはわかりませんが、私がやったこと

$(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>
于 2016-02-29T23:08:13.120 に答える
0

次の例では、すべてのショートカット ロジックをコントローラーに記述し、ディレクティブが他のすべてを処理します。

指令

.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>
于 2015-09-24T14:17:13.990 に答える
0

このライブラリを試すと、ホットキーの管理が非常に簡単になり、アプリをナビゲートするときにキーが自動的にバインドおよびバインド解除されます

angular-ホットキー

于 2015-10-01T16:02:42.610 に答える