skip to Main Content

I have such directive:

@Directive({
  selector: '[imgTest]',
})
export class ImgTest implements AfterViewInit, OnDestroy {

  private originalImage: HTMLImageElement;
  private secondImage: HTMLDivElement;

  constructor(private elementRef: ElementRef, public sanitizer: DomSanitizer) {}

  @HostListener('load')
  public onLoad(): void {
    this.process();
  }

  public ngAfterViewInit(): void {
    this.originalImage = this.elementRef.nativeElement;
  }

  public ngOnDestroy(): void {
    this.removeEventListeners();
  }

  private addEventListeners(): void {
    this.originalImage.addEventListener('mousemove', this.moveImage);
    this.secondImage.addEventListener('mousemove', this.moveImage);
  }

  private removeEventListeners(): void {
    this.originalImage.removeEventListener('mousemove', this.moveImage);
    this.secondImage.removeEventListener('mousemove', this.moveImage);
  }

  private process(): void {
    if (!this.originalImage) {
      return;
    }

    /* some magic */

    this.addEventListeners();
  }

  private moveImage(e: MouseEvent): void {
    let pos: { x: number; y: number }, x: number, y: number;
    e.preventDefault();
    /* some magic that is using also this.getPos(e) */
  }

  private getPos(e: MouseEvent): { x: number; y: number } {
    /* some magic */

    return { x: x, y: y };
  }
}

and the issue is that inside moveImage this is wrong and it’s just not working at all.
what I’ve done wrong?

2

Answers


  1. It’s because inside the addEventListener, this keyword doesn’t refer to the class. You should modify your code to the following:

      constructor(private elementRef: ElementRef, public sanitizer: DomSanitizer) {
        this.moveImage = this.moveImage.bind(this);
      }
    

    After binding moveImage, it will work as expected

    Login or Signup to reply.
  2. when you are adding a listener like this

    this.originalImage.addEventListener('mousemove', this.moveImage);
    

    you are basically breaking "this" reference.

    to preserve correct "this" it you could add a listener in an other way – you should create another callback which would call the method in the correct context

    this.originalImage.addEventListener('mousemove', (e) => this.moveImage(e));
    // or
    this.originalImage.addEventListener('mousemove', this.moveImage.bind(this));
    // or
    boundMoveImage = this.moveImage.bind(this) // somewhere inside of a class
    ...
    ...addEventListener('mousemove', this.boundMoveImage); // this way you could removeEventListeners in remove callbacks
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search