5

Due to a module, the Drupal behavior I implemented is called five times instead of once.

(function ($) {
  Drupal.behaviors.myFunction = {
    attach: function (context, settings) {
      // …
    }
  };
})(jQuery);

How do I correctly use jQuery once()?

1
  • Are you using Drupal 7, or Drupal 8? The method is slightly different depending on the version.
    – Jaypan
    Aug 24, 2017 at 8:53

2 Answers 2

27

You can use $.once(), which is available in both Drupal 7 and Drupal 8. The code called inside $.once() will only be executed a single time for the HTML element it is called on.

For Drupal 7, you can do this.

(function ($, Drupal) {

  function someElementWatcher(context) {
    // $.once acts like $.each, and loops through the found elements.
    // The code inside $.once() will act on each element in the jQuery object
    // a single time.
    $(context).find(".some_element").once("some-arbitrary-but-unique-key", function () {
      // $(this) refers to the current instance of $(".some_element")
      $(this).click(function () {
        // Do something clicky.
      });
    });
  }

  Drupal.behaviors.someUniqueKey = {
    attach:function (context) {
      someElementWatcher();
    }
  };
}(jQuery, Drupal));

In Drupal 8, the $.once() functionality has changed under the hood, and the method of setting it has changed on the front end. In Drupal 8, $.once() needs to be combined with $.each(). You need to change the following part.

$(context).find(".some_element").once("some-arbitrary-but-unique-key", function () {});

Instead, you need to use this.

$(context).find(".some_element").once("some-arbitrary-but-unique-key").each(function () {});

In Drupal 9, once() stopped to be a jQuery function. To use once() library, first add core/once as dependency of the relevant library in the .libraries.yml file.

some_library:
  css:
    ...
  js:
    ...
  dependencies:
    - core/once

You can now use once() to retrieve a list of elements and loop through them.

const elements = $(context).find(".some_element").once("some-arbitrary-but-unique-key");
elements.each(function () {
  // Do something with the current element.
});
1
  • 2
    You need to add core/jquery.once as dependency in the .libraries.yml file.
    – Baach
    Dec 14, 2020 at 0:02
6

Drupal provides the jquery plugin once(), which allows you to ensure a function is run only once on any single element. You can use this within your behaviour.

See Drupal.behaviours here: https://www.drupal.org/docs/8/api/javascript-api/javascript-api-overview

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.