rpayanm
7/12/2019 - 8:39 PM

Attach a Library

Libraries can be attached to all pages, a subset of pages, or to elements in a render array. This allows you to have some assets that are global, and others that are only loaded on an as-needed basis.

Note: While the example below covers how to attach a library in a theme, the same steps work for modules. In the case of modules you'll most likely want to use #attached as part of a Render Array.

  • Attach a library globally to all pages
  • Attach a library to a specific page
  • Use #attached to add a library conditionally via a preprocess function
  • Attach a library from a Twig template

Attach a library globally

Note: You can only attach libraries in themes

In order to attach a library globally, or to every page on your site, you can specify the library in your THEMENAME.info.yml file. Since our site is using a custom theme (called Retro), we'll open up /themes/custom/retro/retro.info.yml

name: retro
type: theme
description: An amazing Retro theme
package: Other
core: 8.x
libraries:
  - retro/global-styling
  - retro/rainbow
  - retro/retro

base theme: bartik

Any libraries specified here in the THEMENAME.info.yml file will be made available on every page. Because of this you'll want to take extra care with this approach. With an asset library that provides something like an analytics tracking code this global approach might be a good idea. Often, however, you don't actually need an asset library on every single page.

Attach a library to a specific page

In most cases it's best to restrict the conditions in which your library is attached to a page. So let's remove our library from retro.info.yml and figure out how to add it on only the front page.

One method of conditionally restricting when your library is attached is to use the hook_page_attachments_alter function in our retro.theme file or in a module's *.module file.

/**
* Implements hook_page_attachments_alter
*/
function retro_page_attachments_alter(array &$page) {
  // Get the current path.
  $path = \Drupal::service('path.current')->getPath();
  // If we're on the node listing page, add our retro library.
  if ($path == '/node') {
    $page['#attached']['library'][] = 'retro/retro';
  }
}

By implementing hook_page_attachments_alter() we're able to add conditional logic that determines whether or not our asset library will be included on the page. In the example here we're only adding the retro library to the node listing page (the default front page).

Use #attached to add a library conditionally via a preprocess function

Another useful way to conditionally add a library is by using a preprocess function like hook_preprocess_page(). Here's another example of restricting our retro asset library to the front page.

/**
* Implements hook_preprocess_page() for PAGE document templates.
*/
function retro_preprocess_page(&$variables) {
  if ($variables['is_front'] == TRUE) {
    $variables['#attached']['library'][] = 'retro/retro';
  }
}

This method of attaching a library works in preprocess functions, in manipulating form elements, or render arrays.

Attach a library from a Twig template

Asset libraries can also be attached from within a Twig template using the attach_library filter. Anytime that template is used the corresponding library will be attached in accordance with any template-specific conditions.

In order to see this in action, we need to create a template in our Retro theme. Since we're using Bartik as our base theme, we can copy the node.html.twig from Bartik into our theme directory. After rebuilding the cache, we can see this new template in action. Let's add a bit of code so that our retro library is only added to the page if we're viewing node 1.

{# only attach our retro library if this is node 1 #} 
{% if node.id == 1 %}
  {{ attach_library('retro/retro') }}
{% endif %}

With this in place, visiting node 1 we can see our retro library in action. Visiting any other node we can see that our library (nor any of its dependencies) has not been attached to the page.