Search code examples
javascriptangularjsangularjs-scopemousetrap

Mousetrap key bindings updating $scope but not detected by $watch.


Basically I have created a function to update a scope variable

// controller.js

$scope.variable = 0;
$scope.$watch('variable', function(){
  console.log("change from watch");
});

$scope.increment = function(){
  $scope.variable++;
  console.log($scope.variable)
}

When I bind a key to this function,

Mousetrap.bind('j', $scope.increment)

the console.log in the browser shows that the variable is incremented when the key, in this case "j", is being pressed, but the $scope.$watch function above is never called and the console.log message "change from watch" is not fired.

When I attach a click handler, however, on the html file,

// index.html
<a ng-click="increment()">{{ variable }}</a>

The variable increases, the console.log shows that the $scope.variable is incremented and the $watch function is being fired as well.

In addition to this problem, {{ variable }} does not change when I use the key binding, yet it changes when I click on it.

My guess is that there is something lacking in Mousetrap that causes the function to fire but not in sync with AngularJS $scope?


Solution

  • Make sure you read about Databinding in AngularJS. Basically, in order for AngularJS to react to changes, something needs to trigger a $digest. The built-in ngClick directive does that under the hood.

    When using non-AngularJS APIs (such as Mousetrap), you need to manually wrap the callback in $apply, e.g.:

    Mousetrap.bind('j', () => $scope.$apply($scope.increment));