Javascript in

Drupal 8

© Arnold PÉTER 2015

 

Only the JavaScript required on a particular page will be added to that page. In particular, by default Drupal doesn't need JavaScript on most pages that anonymous users can see. This means that jQuery is not automatically loaded on all pages anymore.


So, if your theme requires jQuery or some other JavaScript to be present (which also is defined in an asset library), you need to tell Drupal that this is the case, by declaring a dependency on the needed asset library.

Differences with Drupal 7

Differences with Drupal 7

Changes

Drupal.settings => drupalSettings

Drupal.theme.prototype => Drupal.theme

Drupal.ajax.prototype.commands => Drupal.AjaxCommands.prototype

Coding Standards

The first thing to be aware of is that JSHint is now used to check the syntax and coding standards of JS files in core. You can see the current JSHint configuration in the issue queue.

JSHint is a tool to detect errors and potential problems in JavaScript code.

The dark side has fallen

drupal_add_js()
scripts[]

For examples see: core/core.libraries.yml

#attached
hook_library_info() is replaced by $extension.libraries.yml files

The Drupal 8 way

(Yoda approved)

New stuff

  • Backbone.js and Underscore.js are bundled into Drupal 8.
  • Underscore.js is a set of utilities for making writing JS a bit easier while backbone.js is a framework for using JS at an application level.
// Underscore.
$libraries['underscore'] = array(
  'title' => 'Underscore.js',
  'website' => 'http://underscorejs.org/',
  'version' => '1.4.0',
  'js' => array(
    'core/assets/vendor/underscore/underscore.js' => array('group' => JS_LIBRARY, 'weight' => -20),
  ),
);

// Backbone.
$libraries['backbone'] = array(
  'title' => 'Backbone.js',
  'website' => 'http://backbonejs.org/',
  'version' => '0.9.2',
  'js' => array(
    'core/assets/vendor/backbone/backbone.js' => array('group' => JS_LIBRARY, 'weight' => -19),
  ),
  'dependencies' => array(
    array('system', 'underscore'),
  ),
);

Defining a library

To define one or more (asset) libraries, add a *.libraries.yml file to your module folder. (If your module is named fluffiness, then the file name should be fluffiness.libraries.yml). Each "library" in the file is an entry detailing CSS and JS files (assets), like this:

cuddly-slider:
  version: 1.x
  css:
    theme:
      css/cuddly-slider.css: {}
  js:
    js/cuddly-slider.js: { myAttribute }
  dependencies:
    - core/jquery

Attaching to a certain '#type'

(for all instances of it)

To attach a library to a certain existing '#type', for all instances of it, we use hook_element_info_alter():

<?php
function fluffy_element_info_alter(array &$types) {
  if (isset($types['table'])) {
    $types['table']['#attached']['library'][] = 'fluffy/fancy_table';
  }
}
?>
arnold:/var/www/drupal8 (8.0.x)$ drush cache-rebuild
Cache rebuild complete. 

be aware of cacheing

Attaching to a render array

To attach a library to a render array (and perhaps a specific instance of a certain '#type'), you must have access to that render array.

Perhaps you're defining the render array. Perhaps you're modifying it in a hook. In either case, it will look somewhat like this:


<?php
$build['the_element_that_needs_the_asset_library']['#attached']['library'][] = 
    'fluffy/fancy_element';
?>

Attaching to a render array of a Block Plugin

To give another example of attaching a library to a render array, If you are building a block plugin in your module, you can attach the libraries to the render array in the build() function of your class extending the BlockBase class.

<?php
    return array(
      '#theme' => 'your_module_theme_id',
      '#someVariable' => $some_variable,
      '#attached' => array(
        'library' =>  array(
          'your_module/library_name'
        ),
      ),
    );
?>

Attaching a library to all

(or a subset of) pages

In some cases, the asset library is not associated with a certain part of the page, because it is associated with the entire page. For this case, hook_page_attachments() exists. A clear example can be found in the Contextual Links module:

<?php
function contextual_page_attachments_alter(array &$page) {
  if (!\Drupal::currentUser()->hasPermission('access contextual links')) {
    return;
  }

  $page['#attached']['library'][] = 'contextual/drupal.contextual-links';
}

Attaching a library in a

twig template

You can also attach a library in a twig template by using the attach_library() twig function. So in any *.html.twig:

{{ attach_library('contextual/drupal.contextual-links') }}

<div>Some markup {{ message }}</div>

Attaching configurable JavaScript

In some cases, you may want to add JavaScript to a page that depends on some computed PHP information.

In this case, create a JavaScript file, define and attach a library just like before, but also attach JavaScript settings and have that JavaScript file read those settings, via drupalSettings.

$build['#attached']['drupalSettings']['fluffiness']['cuddlySlider']['foo'] = 'bar';

Then cuddly-slider.js will be able to access drupalSettings.flufiness.cuddlySlider.foo

and it will === 'bar'.

Inline JavaScript

Inline JavaScript is discouraged. It's recommended to put the JS you want to use inline in a file instead, because that allows that JavaScript to be cached on the client side. It also allows JavaScript code to be reviewed.

In the other case, the JS belongs in the module:

function fluffy_page_attachments(array &$page) {
  $page['#attached']['html_head'][] = [
    // The data.
    [
      // The HTML tag to add, in this case a <script> tag.
      '#tag' => 'script',
      // The value of the HTML tag, here we want to end up with <script>alert("Hello world!");</script>.
      '#value' => 'alert("Hello world!");',
    ],
    // A key, to make it possible to recognize this HTML <HEAD> element when altering.
    'hello-world'
  ];
}

Drupal 8 = REST API

For example Drupal 8 as BE and Angular front see:

http://travistidwell.com/presentations/drupal-angular

https://github.com/travist/

Drupal 8 Ajax API

https://www.drupal.org/node/2053901

http://www.bluespark.com/blog/new-javascript-libraries-drupal-8

http://atendesigngroup.com/blog/looking-at-drupal-8-javascript-changes

https://www.drupal.org/theme-guide/8/assets

https://www.drupal.org/node/2216195

https://www.drupal.org/node/1664940

https://www.acquia.com/blog/ultimate-guide-drupal-8-episode-5-front-end-developer-improvements (Angela B.)

Links

The end.

For the demo project please contact me at:

Mail: parnold90@gmail.com

Skype: pet.arnold

Linkedin: https://ro.linkedin.com/pub/arnold-peter/58/228/8a2

Twitter: @PeterAArnold

Javascript in Drupal 8

By Arnold PÉTER