Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

problems with keypress events in angular

I'm new to Angular, help will be much appreciated. I'm making an app which has different areas, let's call it pages (even though it's truly a 1 page app) for which I naturally use different views, and I have a common layout with the body, styles and scripts etc.

I'm running into a problem in which I want to listen to keyboard events in only one of the pages of the app which is meant to be interactive while the others are administrative. I can bind keyboard events to inputs or to the document or body. Input is not suitable and my document and body are global and I don't want to listen for every single keypress in my app.

What am I supposed to do to solve this problem in Angular?

My code is here: https://github.com/mgenev/geminiFc/blob/master/public/js/controllers/practice.js

I cheated with jQuery and bound the event to the body in the controller for the particular page, but Angular wasn't reacting like an event happened.

$('body').keydown(function(e) {
            $scope.changeIndex(e);
});

Then I read I have to use $scope.$apply(); which I did in the bottom of the changeIndex function which the event fires.

This actually worked, but when I call the changeIndex through a click event which is the alternative way of controlling my UI

   <div class="practice-controls-bottom">
        <i ng-click="changeIndex('down');" class="icon-thumbs-down icon-4x thumbs-down"></i>
        <i ng-click="changeIndex('up');" class="icon-thumbs-up icon-4x thumbs-up pull-right"></i>
    </div>

Angular gives me an error:

Error: $apply already in progress
    at Error (<anonymous>)
    at g (http://localhost:3000/lib/angular/angular.min.js:85:37)
    at Object.e.$apply (http://localhost:3000/lib/angular/angular.min.js:89:129)
    at Object.$scope.changeIndex (http://localhost:3000/js/controllers/practice.js:173:20)

Looking forward to some advice. Thanks!

like image 771
mobetta Avatar asked Mar 23 '23 03:03

mobetta


2 Answers

You can try either one of the following solutions

Call the $scope.$apply in the keydown handler instead of changeindex method

$('body').keydown(function (e) {
    $scope.$apply(function () {
        $scope.changeIndex(e);
    })
});

or check whether the code is running within a apply/digest cycle before calling $apply in changeIndex again like

if(!$scope.$$phase){
    $scope.$apply()
}
like image 134
Arun P Johny Avatar answered Apr 01 '23 13:04

Arun P Johny


Did you have a look at the ng-keypress, ng-keyup, ng-keydown directives? That way, you could only set the directive on the element inside the view you have to listen to keypresses.

Doc: http://docs.angularjs.org/api/ng.directive:ngKeypress

EDIT: Add tabindex="0" to enable key events on any element.

Here is a working demo: http://plnkr.co/edit/whXgmQU1pKjuRqvokC2Z

html

<div ng-keypress="changeIndex($event)" tabindex="0">Something</div>

js

app.controller('MyCtrl', [function($scope) {
    $scope.changeIndex = function($event) {
        // $event.keyCode...
    }
}]); 

There is also a directive in Angular-UI http://angular-ui.github.io/ui-utils/ that let you associate key combinaisons with functions.

<div ui-keypress="{13:'changeIndex($event)'}"></div>
like image 27
jpmorin Avatar answered Apr 01 '23 11:04

jpmorin