I'm building an app in Angular and I'd like to have keypress events. However, I'd prefer not to litter my code with a keypress here and a keypress there, but rather to put all keypress events into a single factory (or service) and then import this factory into my controllers to use.
I HOPE that doing things this way will make it easier for me to manage the keypress events and make sure I don't have conflicts (two events tied to the same keypresses) or something like that.
Does anybody have any suggestions on how to manage this?
I'm using angular-ui-keypress.
As an example of how I'm hoping to use keypress events.
The user may have multiple tabs open and hits 'cmd+s' to save the files. Rather than a 'save' method being triggered on each of the open files, I've got an OpenFilesFactory, the keypress would map to the OpenFilesFactory.saveFiles method.
Am I going about this all wrong? Is there a reason not to tie keyboard shortcuts to a factory rather than in a controller?
What I ended up doing worked surprisingly well, and I'll opensource it as a module after a bit more work.
I created a directive, which binds to the keypress events on $document
angular.module('keypress', []).directive('keypressEvents', function($document, $rootScope) { return { restrict: 'A', link: function() { $document.bind('keypress', function(e) { $rootScope.$broadcast('keypress',e , String.fromCharCode(e.which)); }); } } })
I then created a second directive for watching for keypresses on specific elements, basically giving the element a focus for key events.
angular.module('focus', []).directive('onFocus', function() { return { restrict: 'C', link: function(scope) { scope.$on('keypress',function(e,parent_evt,key){ if(scope.keyBindings[key]){ scope.keyBindings[key](parent_evt, e); // params reversed so user goes up the chain } }); } } });
In any controller where you want to use keyboard shortcuts, add a keybindings object
function keyedS(key, parent_evt, evt){ // key is the key that was pressed // parent_evt is the keypress event // evt is the focused element object } $scope.keyBindings = { 's': keyedS }
Feedback?
I've actually put this together with multiple keybindings, so if the user selects 'ctrl-shift-s', that is what gets passed along the chain. Though I'm still struggling to find a really good way of getting all the press events. Eg. Tab doesn't work at the moment.
I get what you mean by having it be a separate resource. To me, it seems to go against thinking in Angular, as events really should be "controlled." If you want to have all keypress (or click) events centralized, maybe a switch/case is in order:
$scope.keypressHandler = function () {
switch ($event.keyCode)
{
case 13:
$scope.someEnterKeyFunction();
break;
default:
$scope.someDefaultFunction();
break;
}
}
来源:https://stackoverflow.com/questions/20986240/angular-js-keypress-events-and-factories