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:
// The enclosure receives three arguments, the last being the global // drupalSettings object. (function ($, Drupal, drupalSettings) { const doSomething = function() { // A value in the global drupalSettings object is accessed for comparison. if (drupalSettings.someKey === 'some_value') { // Do something. } } Drupal.behaviors.someBehavior() { attach: function () { doSomething(); } }; // The globals jQuery, Drupal, and Drupal settings are passed to the enclosure. })(jQuery, Drupal, drupalSettings);
Now look at the example using the settings
variable from the attach handler:
// The enclosure receives two arguments. the drupalSettings object is NOT // one receieved. (function ($, Drupal) { // This function is called with one argument that contains the settings const doSomething = function(settings) { // Settings is the value passed to this function from the attach() // handler. if (settings.someKey === 'some_value') { // Do something. } } Drupal.behaviors.someBehavior() { attach: function (context, settings) { // The settings argument is passed to doSomething() doSomething(settings); } }; // The globals jQuery andDrupal are passed to the enclosure. The global // drupalSettings object is NOT passed. })(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.