ディレクティブを使うべきだと思うのですが、ボディにディレクティブを追加するのは奇妙に思えますが、ドキュメントのイベントをリッスンします。
これを行う適切な方法は何ですか?
更新: AngularJS UI を見つけて、keypress ディレクティブの実現を見ました。
ディレクティブを使うべきだと思うのですが、ボディにディレクティブを追加するのは奇妙に思えますが、ドキュメントのイベントをリッスンします。
これを行う適切な方法は何ですか?
更新: AngularJS UI を見つけて、keypress ディレクティブの実現を見ました。
より適切な方法 (または「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>'
};
}
]);
使用$document.bind
:
function FooCtrl($scope, $document) {
...
$document.bind("keypress", function(event) {
console.debug(event)
});
...
}
まだ保証することはできませんが、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);
これが私が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>
キーボード ショートカット用の 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 ドキュメント コードで行われる方法です。つまり、 を押し/
て検索を開始します。
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 の代替バージョン
ショートカットのサービスを作りました。
次のようになります。
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);
}
})
}
}
})
それは良いです。
それが本当の角度のある方法かどうかはわかりませんが、私がやったこと
$(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>
次の例では、すべてのショートカット ロジックをコントローラーに記述し、ディレクティブが他のすべてを処理します。
指令
.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>
このライブラリを試すと、ホットキーの管理が非常に簡単になり、アプリをナビゲートするときにキーが自動的にバインドおよびバインド解除されます