Our Thoughts
Aastha Shrivastava
Full Stack Engineer
27 December, 2021 4 MIN READ

Attaching custom libraries to a component/template in Acquia Site Studio

Acquia Site Studio is a low-code, Drupal add-on available for Acquia subscribers which allows users to create sites using drag and drop Layout Canvas, empowering non-developers in marketing or other departments, designers with little coding knowledge to create unique layouts with fully customizable CSS.

While Site Studio allows users to add custom CSS to each component/element there is currently no way to add JS directly to a component or element or template. This means that if a component needs custom JS, the user will have to write it in the theme’s global JS file which will be included on every page of the site.

This can create problems if two or more components have conflicting JS, and it can also lead to performance and security issues since even though a component appears on just a few pages, the JS code related to it is included on every page. In this article, we will explore how to create a custom element that can add a custom library to any component/template.

Let’s get into it!

1. Setting up files

1.1 Creating/Editing custom module

Let's start by finding a home for our custom element's files, for this, you can either use your existing custom module or create a new one.

1.2 Adding dependency

For creating a custom element, our module should have cohesion in the list of dependencies.

Let's go ahead and make changes to the info.yml file of our module.

dependencies:
  - cohesion

1.3 Creating required files

Our custom element file should be placed in the src/Plugin/CustomElement directory, so the directory structure looks like this:

additional_js_controller
└──src
   └──Plugin
      └──CustomElement
         └──AdditionalJS.php

 

2. Creating a custom Site Studio element

2.1 Setting up the class

We can create a custom Site Studio element by extending the CustomElementPluginBase class.

/**
 * Element to attach custom libraries.
 *
 * @package Drupal\cohesion\Plugin\CustomElement
 *
 * @CustomElement(
 *   id = "additional_js",
 *   label = @Translation("Additional JS Controller")
 * )
 */
class AdditionalJS extends CustomElementPluginBase

2.2 Adding methods

There are two methods we need to override to create our element:

  • getFields()
  • render() 

As the name suggests, the getFields() method returns fields that are needed to build this element, and the render() method returns a render array of the element.

public function getFields() {
    return [
      'library' => [
        'type' => 'textfield',
        'placeholder' => 'my-project/my-library',
        'title' => 'Library',
      ],
    ];
  }

Here we have added a text field to accept the name of the library to be attached.

public function render($element_settings, $element_markup, $element_class, $element_context = []) {
    $build['#attached']['library'][] = $element_settings['library'];
    return $build;
  }

The values that we accepted in fields created by getFields() method can be retrieved from the $element_settings array, here we are just retrieving the value of the library field and adding it in the $build render array, and finally returning the $build render array.

You can refer to the full documentation for creating a custom element here.

So our complete code looks like this:

namespace Drupal\additional_js_controller\Plugin\CustomElement;

use Drupal\cohesion_elements\CustomElementPluginBase;

/**
 * Element to attach custom libraries.
 *
 * @package Drupal\cohesion\Plugin\CustomElement
 *
 * @CustomElement(
 *   id = "additional_js",
 *   label = @Translation("Additional JS Controller")
 * )
 */
class AdditionalJS extends CustomElementPluginBase {
  public function getFields() {
    return [
      'library' => [
        'type' => 'textfield',
        'placeholder' => 'my-project/my-library',
        'title' => 'Library',
      ],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function render($element_settings, $element_markup, $element_class, $element_context = []) {
    $build['#attached']['library'][] = $element_settings['library'];
    return $build;
  }

}


3. Adding our custom element to a component

Now it’s time to see our custom element in action!

Make sure you have enabled our module, then create a new component or edit an existing one and you should be able to see our custom element in the Custom elements category at the end.

Attaching custom libraries to an element in Acquia Site Studio

Let's go ahead and add this to our element.

Attaching custom libraries to an element in Acquia Site Studio

Go ahead and edit the element, and you will see the field created earlier.

Attaching custom libraries to an element in Acquia Site Studio

Add the name of your library and save it.

Here we are assuming that awesomeness is a custom theme and its libraries.yml file looks something like this:

scroll-to-top:
 js:
   js/scroll-to-top.js: {}
 dependencies:
     - core/jquery
     - core/jquery.once

You can use the library present in any module or theme.

Attaching custom libraries to an element in Acquia Site Studio


Et voila! We are done, you should be able to see your JS file in the page source wherever this component is present.

Note: Even though we are primarily focusing on attaching a custom JS library, the same element can also be used to attach custom CSS since Drupal follows the same workflow to attach CSS and JS libraries.

 

Aastha Shrivastava