Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to listen for mousemove event on Document object in Angular

Tags:

angular

I am implementing dragging functionality into an angular app: http://jsfiddle.net/Jjgmz/1/

Part of it, is to listen for mousemove event on a document object.

$(document).mousemove(function(e) {}); 

How can I listen for document object inside of a component?

Lets pretend this is the contents of component.html file:

<div id="box"></div> 

I am using Angular 4.

like image 727
sanjihan Avatar asked Sep 24 '17 10:09

sanjihan


People also ask

What is Mousemove event?

The mousemove event is fired at an element when a pointing device (usually a mouse) is moved while the cursor's hotspot is inside it.

Which event is used when mouse moves over the element?

The mouseover event is fired at an Element when a pointing device (such as a mouse or trackpad) is used to move the cursor onto the element or one of its child elements.

How often does the Mousemove event fire?

The frequency rate of events while the pointing device is moved is implementation-, device-, and platform-specific, but multiple consecutive mousemove events SHOULD be fired for sustained pointer-device movement, rather than a single event for each instance of mouse movement.


1 Answers

1) Using @HostListener (docs). This is the prefered method which should be enough most of the time.

import {Component, NgModule, HostListener} from '@angular/core'  @Component({   ... }) export class MyComponent {   @HostListener('document:mousemove', ['$event'])    onMouseMove(e) {     console.log(e);   }   .. } 

2) Similar to the above, you can also use (document:event)="handler" on any DOM element, but the above solution is prefered because the code is cleaner. By using this, it's not immediately obvious from the class that you have a global event listener, and you might add additional ones unnecessarily.

@Component({   selector: 'my-app',   template: `     <div (document:mousemove)="onMouseMove($event)" id="box"></div>   `, }) export class MyComponent {   onMouseMove(e) {     console.log(e);   } } 

3) The Renderer (docs) is a lower-level solution; useful when you do not want to clutter your code with methods, but deal with the even elsewhere, for example in a hook, as the following snippet shows. Be careful, though, as you still need to remove the event listener to prevent memory leaks; either do this when you know you won't need it anymore, or in the OnDestroy hook.

import { Component, Renderer2 } from '@angular/core';  @Component({   ... }) export class MyComponent {   globalListenFunc: Function;    constructor(private renderer: Renderer2) {}    ngOnInit() {     this.globalListenFunc = this.renderer.listen('document', 'mousemove', e => {       console.log(e);     });   }    ngOnDestroy() {     // remove listener     this.globalListenFunc();   } } 

4) Alternative of the first example is a host property, which is discouraged by the Angular Style Guide, since you now keep track of the function name in two places which can be very far apart physically in code. Prefer the first version whenever possible.

@Component({   ...   host: {     '(document:mousemove)': 'onMouseMove($event)'   } }) export class MyComponent {   onMouseMove(e) {     console.log(e);   } } 

5) A reactive way, which Angular embraces, is using Observable.fromEvent. This gives you a benefit of all RxJS operators for transforming the stream before executing a function. Be careful, though, as you need to unsubscribe manually to avoid memory leaks (unless you subscribe directly in the template using async pipe; this will handle unsubscription for you). Also don't forget to add-import the operator, as shown in the following snippet.

import { Subscription, fromEvent } from 'rxjs';  @Component({   ... }) export class MyComponent {   subscription: Subscription;    ngOnInit() {     this.subscription =           fromEvent(document, 'mousemove')                            .subscribe(e => {                              console.log(e);                            });   }    ngOnDestroy() {     this.subscription.unsubscribe();   } } 

6) Of course, document.addEventListener is always a solution as well; but this is not an intended usage in Angular apps; you should choose different ways. Directly accessing DOM is discouraged as it breaks Angular's neat encapsulation of DOM manipulation. Also you could run into problems with Universal and SSR.

like image 120
yurzui Avatar answered Sep 23 '22 07:09

yurzui