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