Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2+ window.onfocus and windows.onblur

So I need in Angular 2 or 4 to manage when the browser tab of my app is focused or not. Is there any way to use the window.onfocus and window.onblur ?

Thanks a lot

like image 800
Ali Briceño Avatar asked Aug 02 '17 18:08

Ali Briceño


3 Answers

You can use a component with @HostListener.

Something like:

@Component({})
export class WindowComponent {

constructor(){}

    @HostListener('window:focus', ['$event'])
    onFocus(event: any): void {
        // Do something
    }

    @HostListener('window:blur', ['$event'])
    onBlur(event: any): void {
        // Do something
    }

}

Just check that you don't have multiple WindowComponent running at the same time, because you will have an unexpected behavior, due that each instance will react to these events.

like image 171
dlcardozo Avatar answered Sep 19 '22 13:09

dlcardozo


Turns out this doesn't work in services, which was my requirement. My solution was doing it "the old way":

@Injectable()
export class WindowService {
    constructor(){
        window.addEventListener('focus', event => {
            console.log(event);
        });
        window.addEventListener('blur', event => {
            console.log(event);
        });
    }
}

Not sure I did it the "correct" way, but it works on Chrome. What I'm not sure about is if I should destroy the event listener or not, and if it works in other browsers. Let me know if I'm inadvertently shooting myself in the foot here. Will update answer if so, or delete it if need be.

like image 40
André C. Andersen Avatar answered Sep 20 '22 13:09

André C. Andersen


In a more reactive approach, I use this injection token:

export const WINDOW_FOCUS = new InjectionToken<Observable<boolean>>(
    'Shared Observable based on `window focus/blurred events`',
    {
        factory: () => {    
            return merge(fromEvent(window, 'focus'), fromEvent(window, 'blur')).pipe(
                startWith(null),
                map(() => window.document.hasFocus()),
                distinctUntilChanged(),
                share(),
            );
        },
    },
);

Ideally, you do not want to rely on the global windows variable, you could replace it with injecting the WINDOW and DOCUMENT tokens from https://github.com/ng-web-apis/common.

To use the WINDOW_FOCUS injection token, in any component or service, it can be added to the constructor like this:

@Injectable()
export class SomeService {
    constructor(
        @Inject(WINDOW_FOCUS) private readonly windowFocus$: Observable<boolean>
    ) {} 
}
like image 43
schmkr Avatar answered Sep 21 '22 13:09

schmkr