1

Let say I want to alert user every time he clicks on <a> tag.

document.querySelector('body').addEventListener('click', function (event : any) {
            if (event.target.tagName === 'A') {
                event.preventDefault();
                alert('Congratulations! A tag clicked!!!');
            }
        });

If I put this binding in constructor (on in ngOnInit()) I will have new binding (and one more alert) every time i go to this component (router link).
What is the way to bind only one time, on the first init?

In the meantime I use removeEventListener() in ngOnDestroy(). It seems to be ugly. Is there anything better?

Shimon S
  • 4,048
  • 2
  • 29
  • 34

1 Answers1

1

It seems like you need to check whether the desired event listener already exists on your element or not. Please refer to: How to check whether dynamically attached event listener exists or not?

Based on this answer I would advise to use something like this (works for me at least):

function showAlert(evt) {
  evt.preventDefault();
  alert('Congratulations! A tag clicked!!');
}

  const aTags = document.querySelectorAll('a');
  for (const i in aTags) {
    const element = aTags[i];
      if (element instanceof Element && element.getAttribute('listener') !== 'true') {
        element.addEventListener('click', showAlert);
        element.setAttribute('listener', 'true');
    }
  }

If you need to bind your event listener to the whole body like in your example, you may use a static variable. Just create one at the beginning of your component and check it's value before binding an event listener. E.g.:

export class CongratulationsComponent implements OnInit {
  static flag = true;
  constructor() {}

  ngOnInit() {
    if (CongratulationsComponent.flag) {
      document.querySelector('body').addEventListener('click', function (event: any) {
        if (event.target.tagName === 'A') {
          event.preventDefault();
          alert('Congratulations! A tag clicked!!!');
        }
      });
      CongratulationsComponent.flag = false;
    }
  }
}