Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is a correct way to bind document level key events in AngularJS specific only to a certain route/controller?

Tags:

angularjs

I have a single page app that opens a gallery. I want to bind document level keyup event (for keyboard gallery controlls) only when the gallery is open, ie. when route matches

.when('/reference/:galleryId/:imageId/', { templateUrl: '/partials/gallery.htm', controller: 'galleryController', controllerAs: 'reference' })

and I want to unbind it when I leave this route.

One thing that might be a problem is, I block reloading the view between images within the same gallery with this:

.run(['$route', '$rootScope', '$location', function ($route, $rootScope, $location) {
    var original = $location.path;
    $location.path = function (path, reload) {
        if (reload === false) {
            var lastRoute = $route.current;
            var un = $rootScope.$on('$locationChangeSuccess', function () {
                $route.current = lastRoute;
                un();
            });
        }
        return original.apply($location, [path]);
    };
}])

Demo (Click on "Fotografie" to open the gallery) http://tr.tomasreichmann.cz/

Angular wiz to the rescue?

Thank you for your time and effort

like image 591
Tom Avatar asked Jul 29 '14 14:07

Tom


People also ask

Which is the correct syntax of creating AngularJS controller?

The ng-controller="myCtrl" attribute is an AngularJS directive. It defines a controller. The myCtrl function is a JavaScript function. AngularJS will invoke the controller with a $scope object.

What is $scope in AngularJS?

The Scope in AngularJS is the binding part between HTML (view) and JavaScript (controller) and it is a built-in object. It contains application data and objects. It is available for both the view and the controller. It is an object with available properties and methods. There are two types of scopes in Angular JS.

What is the use of angular controllers in the application?

All the AngularJS application mainly relies on the controllers to control the flow of data in that application. Basically, it controls the data of AngularJS applications and the controller is a Javascript object, created by a standard JavaScript object constructor.


2 Answers

You could bind a keyup event to $document in your controller's constructor and then unbind the event when the controller's $scope is destroyed. For example:

.controller('galleryController', function ($scope, $document) {
  var galleryCtrl = this;

  function keyupHandler(keyEvent) {
    console.log('keyup', keyEvent);
    galleryCtrl.keyUp(keyEvent);

    $scope.$apply(); // remove this line if not need
  }

  $document.on('keyup', keyupHandler);
  $scope.$on('$destroy', function () {
    $document.off('keyup', keyupHandler);
  });

  ...
});

There will be nothing left behind when the view become inactive.

If you feel it isn't right to do this in the controller, you could move this into a custom directive and place it in a template of the view.

like image 171
runTarm Avatar answered Sep 24 '22 20:09

runTarm


Finally I stuck with

<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:og="http://ogp.me/ns#"
  xmlns:fb="http://www.facebook.com/2008/fbml"
  lang="cz"
  ng-app="profileApp"
  ng-keyup="$broadcast('my:keyup', $event)" >

Not sure if this is good practice, but it registers within my controller

$scope.$on('my:keyup', function(event, keyEvent) {
    console.log('keyup', keyEvent);
    galleryCtrl.keyUp(keyEvent);
});

And doesn't do anything when the current route is not active

I found this answer here: https://groups.google.com/forum/#!searchin/angular/document$20level$20events/angular/vXqVOKcwA7M/RK29o3oT9GAJ

There is another way to bind it globally which wasn't my goal, the original code in question did what I needed.

like image 29
Tom Avatar answered Sep 22 '22 20:09

Tom