Drupal JavaScript API: The difference between drupalSettings and settings

Submitted by Jaypan on

I recently updated the Drupal documentation page on Adding assets (CSS, JS) to a Drupal theme via *.libraries.yml according to a request in the comments of that documentation page:

I don't actually remember the original write-up being referred to, however I decided to add the following section to the documentation page:

The difference between drupalSettings and settings

In the code shown on the documentation page, there is a global reference to the drupalSettings object, as well as a settings object in the attach() handler of the script.

drupalSettings: (function ($, Drupal, drupalSettings) {

settings: attach (context, settings)

There actually is no difference between these variables, in that the settings argument is a pointer to the drupalSettings object. When the Drupal JavaScript API triggers the attach handler, it does so by calling Drupal.attachBehaviors(row, drupalSettings). So the drupalSettings object is passed by reference as settings in attach (context, settings).

One may wonder why they are both provided. This is how Drupal handles multiple scripts that are all enclosed in their own enclosures; as the drupalSettings object is a global variable, it allows for that variable to be  used within the enclosures of multiple scripts. But while it can be used within enclosures, clean development practices will avoid the use of global variables within an enclosure, to keep everything... enclosed. For example, look at an example using the global drupalSettings object:

  1. // The enclosure receives three arguments, the last being the global
  2. // drupalSettings object.
  3. (function ($, Drupal, drupalSettings) {
  4. const doSomething = function() {
  5. // A value in the global drupalSettings object is accessed for comparison.
  6. if (drupalSettings.someKey === 'some_value') {
  7. // Do something.
  8. }
  9. }
  10.  
  11. Drupal.behaviors.someBehavior() {
  12. attach: function () {
  13. doSomething();
  14. }
  15. };
  16.  
  17. // The globals jQuery, Drupal, and Drupal settings are passed to the enclosure.
  18. })(jQuery, Drupal, drupalSettings);

Now look at the example using the settings variable from the attach handler:

  1. // The enclosure receives two arguments. the drupalSettings object is NOT
  2. // one receieved.
  3. (function ($, Drupal) {
  4. // This function is called with one argument that contains the settings
  5. const doSomething = function(settings) {
  6. // Settings is the value passed to this function from the attach()
  7. // handler.
  8. if (settings.someKey === 'some_value') {
  9. // Do something.
  10. }
  11. }
  12.  
  13. Drupal.behaviors.someBehavior() {
  14. attach: function (context, settings) {
  15. // The settings argument is passed to doSomething()
  16. doSomething(settings);
  17. }
  18. };
  19. // The globals jQuery andDrupal are passed to the enclosure. The global
  20. // drupalSettings object is NOT passed.
  21. })(jQuery, Drupal);

The above two examples do the same thing, but the latter does not make use of the global drupalSettings object, and instead passes the settings argument from attach (context, settings) to any functions within the same script enclosure as necessary.