The Drupal JavaScript function once()
is a helper to ensure that callbacks are executed only one time. Although there are multiple other ways to deal with that, it is something that is being used quite frequently to deal with dynamically loaded content.
Originally it was a jQuery plugin which was changed in Drupal 9 to separate function. They still provided BC layer for existing code, but that was removed in Drupal 10.
While it can be straightforward to migrate existing code to new function, there can be some differences that need to be handled differently. One example would be using once() on a document object, as seen on the code below:
$(document, context).once('myUniqueIdentifier').each(function () {
// Code to apply behavior to each element once
});
You would assume that the new code would look like this:
once('myUniqueIdentifier', document, context).forEach(function (document) {
// Code to apply behavior to each element once
});
You might have tried that and wondering why once()
is not working. It doesn't do what it supposed to do because once()
is using data attribute to track identifiers, they can't be added to document
or window
object. One way around it would be to use body element instead:
once('myUniqueIdentifier', 'body', context).forEach(function (document) {
$(document).on('click', function(e) {})
});
Depending on the functionality, you could use different element and skip document, but in some cases it is needed to bind document
or window
object directly (for example handling key press, event delegation etc).
Alternatives
You could use context
variable inside behaviour, but it might not work as expected, as it might give same elements again.
You can stop using behaviours, if the scripts functionality allows it.