Search code examples
angularaddeventlistenerngoninit

Angular. Bind event only one time (on first init)


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?


Solution

  • 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;
        }
      }
    }