fotoflo
fotoflo

Reputation: 977

Detecting window focus the angular way?

Is there a good angular way to detect window focus? I am using html5 notifications and I would like to only fire if the window is out of focus.

Thanks!

Upvotes: 8

Views: 16432

Answers (4)

Kirk Grover
Kirk Grover

Reputation: 195

In Cristi Berceanu's answer, he suggests assigning a function to $window.onfocus, which does work. However, there is a problem with that... only one function can be assigned to $window.focus at a time. Thus, by assigning a function to $window.onfocus, you could accidentally overwrite a previous function, and your function will be vulnerable to being overwritten later, too.

Here's a different solution that allows multiple functions to run with the window's focus or blur events:

var onFocus = function () {
    // do something
};

var onBlur = function () {
    // do something else
};

var win = angular.element($window);

win.on("focus", onFocus);
win.on("blur", onBlur);

This will allow you to assign multiple functions to the focus and blur events for the $window object.

If you added the functions inside a controller and want to remove those functions when the controller is destroyed, you can do something like this:

$scope.$on("$destroy", function handler() {
    win.off("focus", onFocus);
    win.off("blur", onBlur);
    $interval.cancel(interval);
});

Solution inspired by this post: https://www.bennadel.com/blog/2934-handling-window-blur-and-focus-events-in-angularjs.htm

Upvotes: 4

Cristi Berceanu
Cristi Berceanu

Reputation: 1693

There's a built-in angular directive ngFocus here maybe it helps if you attach it to the body

<window, input, select, textarea, a
  ng-focus="">
...
</window, input, select, textarea, a>

Edit: For window focus, there's the $window wrapper and you can do something like:

 $window.onfocus = function(){
   console.log("focused");
 }

Upvotes: 5

Luis Masuelli
Luis Masuelli

Reputation: 12343

Edit @CristiBerceanu is right - you should use the built-in ng-focus directive. However, take this answer as a guideline for any missing event you want to bind.

You must create a directive:

angular
  .module('MyModule', [])
  .directive('onFocus', function(){
    return {
        restrict: 'A',
        scope: {
            'focus': '&onFocus'
        },
        link: function($scope, $element, $attributes) {
            var focus = function(event) {
                $scope.focus({'$event': event});
            };
            $element.on("focus", focus);
            $scope.$on('$destroy', function(){
                $element.off('focus', onClick);
            });
        }
    }
});

Notice how the event is bound in the directive by jquery and NOT directly in the controller. Additionally, notice that a bound expression is tied using the & prefix (evaluable expression binding) instead of regular prefixes like @ (text-binding) or = (scope property reference, bi-directional, binding).

Upvotes: 5

Dayan Moreno Leon
Dayan Moreno Leon

Reputation: 5435

you can write a directive to attach to the body element and inside it you can use $window.onfocus event to notify your angular app using events or a service, the same thing you can do from inside a service, it all depends on your architecture

Upvotes: 1

Related Questions