-1

I am migrating a Drupal 7 site to Drupal 8. I have a custom block (visible only on the home page) that has some tabs on it. Currently, the tabs are implemented using jQuery UI tabs and it would be nice (but not necessary) to keep them using that.

In order to get this to work, I need to use the jQuery and jQuery UI JavaScript files. However, everything I have seen online talks about module and theme dependencies. There doesn't seem to be any way to tell Drupal 8 that a specific block (or page, etc.) needs specific JavaScript files loaded in order to work correctly.

I know that I can just import the javascript files directly with script tags, but that doesn't seem to be the preferred method, especially considering all of the various optimizations that are part of Drupal (to make sure that a file is only included once, for example).

How do I include the required JavaScript files (available in core) on a specific page or as part of a specific block?

I don't really want to create a custom module for every time that I need to do this, but all of the references I have found online talk about dependencies for themes or modules, nothing for specific content.

EDIT: Multiple suggested answers involve PHP, custom modules, YML, etc. These are not what I am looking for. I am looking for a solution for front-end content creation (pages, nodes, blocks for the "custom block library", and so on), not requiring back-end coding and development. Modules on Drupal.org that allow this to be done generically are perfectly acceptable. Maybe I need to create one and put it up there, but I would think there should be an existing solution by now. It seems strange to me that there isn't, but maybe I'm missing something.

  • 2
    "There doesn't seem to be any way to tell Drupal 8 that a specific block (or page, etc.) needs specific JavaScript files loaded in order to work correctly." Yes, there is. You would have to alter some stage of the block build process and add the libraries you need for it with #attached. Same for a page. – Kevin Sep 17 '19 at 0:41
  • @leymannx It's not a duplicate, because that link talks about PHP and themes, which is what most of what that I've found online. I'm looking for a way to do it for a plain HTML page or block that is added via the web interface, not coded on the back end. – Ampersat Sep 17 '19 at 13:48
  • @Kevin Similar to what I said already, #attached is used with PHP. I'm looking for a non-PHP solution (but am fine if there is some kind of generic module available on Drupal.org that can be used to make it work. – Ampersat Sep 17 '19 at 13:50
  • Sorry, but this makes no sense to me. Drupal is written in PHP. You could use the Twig Tweak module to attach a library directly in a template. Still you need this library to be defined in a YML file and edit the corresponding template. If you don't care about performance or SEO you could set your body field format to FullHTML and print a script tag in there. But really, this would be a ridiculous thing to do. Before you do that maybe consider switching to a different CMS. – leymannx Sep 17 '19 at 14:22
  • @leymannx Drupal is written in PHP. However, pages are intended to not use PHP. The PHP filter which was in Drupal 7 was removed from core in Drupal 8, making it clear that such things were considered non-ideal going forward. So if I have a single page that I want to have tabs on or some other fancy thing just for that page and it requires JavaScript libraries (part of core) that are not included by default (which is what Drupal 8 does and recommends), what does Drupal expect someone to do? Create a custom module just for that page? Write PHP just for that page? Isn't there another way? – Ampersat Sep 17 '19 at 14:48
1

For a specific page or content type, do:

/**
 * Implements hook_page_attachments().
 */
function MYMODULE_page_attachments(array &$attachments) {
  if ($node = \Drupal::routeMatch()->getParameter('node')) {
    if ($node->getType() === 'book') { // You can also check on certain ID's here as well.
      // Current page is a Book node.
      $attachments['#attached']['library'][] = 'mymodule/custom';
    }
  }
}

In mymodule.libraries.yml:

custom:
  version: 1.x
  js:
    js/custom.js: {}
  dependencies:
    - core/jquery
    - core/drupalSettings
| improve this answer | |
  • Same as for the other comments, this requires either PHP or YML. I'm looking for a way to do this on the front end when creating a page or a block for the "custom block library", not requiring back end coding. – Ampersat Sep 17 '19 at 13:52
  • @Ampersat i do think you will require custom coding in php or yml to achieve what you want!. – Aditya Joshi Sep 17 '19 at 14:57
1
  1. Define an asset library in mymodule.libraries.yml. An asset library can declare either CSS assets or JavaScript assets, or both. It can also declare dependencies on other asset libraries. For example on jQuery (core/jquery) or perhaps your JavaScript defines a "Drupal behavior", in which case you depend on the supporting infrastructure for that (core/drupal). Ex:

    example_library:
      js: path/to/some/file.js: {}
      dependencies:
        - core/drupal
        - core/jquery
    
  2. Use #attached in your block's render array to attach the asset library:

// Assuming the variable containing your render array is called $build.
$build['#attached']['library'][] = 'mymodule/example_library';

Extensive documentation can be found at https://www.drupal.org/docs/8/creating-custom-modules/adding-stylesheets-css-and-javascript-js-to-a-drupal-8-module.

| improve this answer | |
  • Those look like they work well for custom libraries or for PHP-rendred blocks, but what about plain HTML code that would be on a page or in a block created for the "custom block library"? There's no PHP or YML involved in either of those. So how do you tell Drupal that you need specific JavaScript libraries available for them? – Ampersat Sep 17 '19 at 13:44

Not the answer you're looking for? Browse other questions tagged or ask your own question.