Drupal implements its own Javascript API. Most of the time, all code should use behaviors that trigger every time something changes on the page - page loaded, ajax request, and so on. On the other hand, it causes issues with code executing more than one time.
Below is a basic example of listening to click events on elements with class .js-click
.
(function (Drupal) {
Drupal.behaviors.MyModule = {
attach: function attach(context) {
once('myModuleClick', '.js-click', context).forEach(element => {
element.addEventListener('click', e => {
alert('Element click');
});
});
}
};
})(Drupal);
If you need to listen to click events on the document
object, then it's a bit trickier. Because once()
doesn't work with that, we need to workaround, and usually applying to body
element works, because it appears only one time in HTML. Inside of it, add event listened to the document
object directly.
(function (Drupal) {
Drupal.behaviors.MyModule = {
attach: function attach(context) {
once('myModuleClick', 'body', context).forEach(() => {
document.addEventListener('click', e => {
alert('Document click');
});
});
}
};
})(Drupal);
It is also possible to use context variable to select changed elements inside of it, but I have seen that in some cases (looked like BigPipe), it caused behaviours to apply multiple times with whole document context.
Hopefully it helped.
If you are looking for info, how to migrate from jQuery.once(), check out this article