How to use once() in Drupal

Once is a Drupal library - available on npm - that ensures your JavaScript only runs once when working on any item.

I put a snippet on a Slack channel recently suggesting that someone should use once() to make sure their code didn't run multiple times. And then I gave them this snippet to show how to use it:

const editFrequencys = once('allEditFrequencies', '.edit-frequency', context);

editFrequencys.forEach(editFrequency => {
  editFrequency.on('change', function() {
    $.ajax({
      method: "POST",
      url: "/frequency-select",
      data: { name: "John", location: "Boston" },
      dataType: "json"
    })
      .done(function( data ) {
        console.log("It's done!");
        console.log(data);
      });
  });
});

Job well done, Mark, you might say. Yes, but then the author asked me:

What are the different arguments about in the first line?
I've seen this code in searching for an answer, but nothing ever explains what/why the arguments for the "once" are for.

And that reminded me of a younger me. Me about 6 months ago, when I first tried to use once(). So here is the explanation I gave them:

const editFrequencys creates a variable for what you want to work on. It’s a plural, because once always returns an array. You could do something like const [editFrequency] to just return one item if you were sure there was only ever going to be one of the thing you are looking for on the page. But I find it better to return the array just in case in the future a second instance of the thing is on the page.

once() is the function that will ensure the code that is acting on your “thing” will only act once.

'allEditFrequencies' is a name that we assign to this item. You can assign anything to it basically, such as 'justSomeStuff'. This is then attached to the property in your DOM via a data attribute, such as data-once="allEditFrequencies" so JS knows which once function this item belongs to.

context is just the method that is going to be used to find your array. You could use document here, but if the page gets updated via ajax, then document will not be updated, so in Drupal terms, context is probably better.

If I got something wrong there, or there's something I should update, let me know.

Filed Under:

  1. Drupal
  2. Drupal Planet