0

I would like to use DataTables.js for tables created by content editors in the main body field of a content type. I already have the library installed in my libraries.yml.

I had an idea that I could avoid calling the library globally, but instead have it only be called on a page that has an HTML <table> element rendered.

That idea came from drupal.org documentation here, which offers up this code example for the hook_element_info_alter() function:

function fluffy_element_info_alter(array &$types) {
  if (isset($types['table'])) {
    $types['table']['#attached']['library'][] = 'fluffiness/fancy_table';
  }
}

However when I checked into the theme.api, I saw this code is intended for people making modules and indeed the documentation section I saw it in was for modules.

Can I use this same or similar bit of code in my theme_name.theme file to apply to all nodes? Is there something else I should do instead?

Thanks for any advice you can offer.

5
  • Correct, that is only for element theming.
    – Kevin
    Feb 1, 2017 at 20:00
  • Correct, in that I can use it to theme the table element (and all its rows inside)?
    – LeraA
    Feb 1, 2017 at 20:05
  • No, element in this case does not mean basic HTML tag, it refers to form elements. There is no hook that will parse a body field and pick up on table tags.
    – Kevin
    Feb 1, 2017 at 20:10
  • I would either attach the library to node types that have a body field, or look at the body field content and regex for '<table' - if there is a match, attach the library.
    – Kevin
    Feb 1, 2017 at 20:30
  • @Kevin, I really appreciate your input, thanks. I don't even begin to know how to do what you said. Can you point me to any documentation or examples I could use to start understanding?
    – LeraA
    Feb 1, 2017 at 21:06

1 Answer 1

1

hook_element_info_alter won't suit in this situation because you are trying to do something based on the value of a body field, which is just 'text' as far as Drupal is concerned. Element in the Drupal world is different. But here is an approach to your problem.

You can implement hook_preprocess_node and check if the body field value contains <table - and if there is a hit, then attach the library:

use Drupal\Component\Utility\Unicode;

function mytheme_preprocess_node(&$variables) {
  $node = $variables['node'];
  $match = Unicode::strpos($node->field_body->value, '<table');

  if ($node->field_body->value && $match !== FALSE) {
    // next line is just an example
    $variables['#attached']['library'][] = 'mytheme/libraryname';
    $variables['#attached']['library'][] = 'mytheme/datatables';
  }
}

This will only attach the library to a node being rendered IF the node body field has a value, and within it, there is a match for an opening table tag.

The use statement should go at the top of your mytheme.theme file.

strpos has a caveat:

Note that a return value of 0 is not the same as FALSE.

So if you plan on using this a little more elsewhere, take note.

2
  • To @Kevin and all the folks like him who take the time to craft an answer like this, I really want to express my gratitude. Not only did Kevin's answer work great for me but it's also building my understanding of pre-processing. This answer keeps on giving because it's thorough in explaining some opaque concepts and I'm growing as a developer. Thanks again for investing your time in the community.
    – LeraA
    Feb 3, 2017 at 15:35
  • No problem. Preprocess hooks are a good way to do things like this.
    – Kevin
    Feb 3, 2017 at 15:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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