Search code examples
javascriptjqueryeventsangularjskeypress

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!


Solution

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