2

I have a javascript library with several separate files which I would like to include only if necessary. I currently determine which need to be included within the twig template.

{{ attach_library('flot_d8/flot') }}
{% if options['xaxis']['mode'] == 'categories' %}
{{ attach_library('flot_d8/categories') }}
{% endif %}

{% if options['selection'] is defined %}
{{ attach_library('flot_d8/selection') }}
{% endif %}

{% if options['pan'] is defined %}
{{ attach_library('flot_d8/navigate') }}
{% endif %}

{% if resizable == true %}
{{ attach_library('flot_d8/resize') }}
{% endif %}

{% if nodiv == false %}
<div id="{{div_id}}" style="width:600px;height:300px;"></div>
{% endif %}

Is there a better, or alternative way to perform this logic? I would like to override this template in another module and make the simple <div> element more complex. However, I would have to copy all the library inclusion logic with it.

  • Use the #attached attribute. – Eyal Jan 21 '16 at 15:28
  • What hook should I use to place my if statements and add the #attached attribute? And how do I get this hook to read the values of the #options attribute that is passed to it? – Kevin Nowaczyk Jan 21 '16 at 15:45
  • That depends on the situation. You can add the #attached attribute to any render array. – Eyal Jan 21 '16 at 20:01
1

Attaching libraries in Drupal 8 should be done by either attaching the #attached attribute to render arrays or by adding them to the info file to be added to all pages.

For example let's say I have a custom form class that needs my custom javascript and/or css files.

class MyForm extends FormBase {
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['#attached']['library'][] = 'my_module/my_library'
    return $form;
  }
}

If you want to attach a library to an element you didn't initiate then you will need to use an alter hook for that specific element. If you want to attach a library based on other conditions then you can use the hook_page_attachments(array &$attachments) function

  • My module currently has an empty src directory. It's just an info file, template, module file and some css and js. I am not at all opposed to adding a class structure to it if it's "The Drupal Way" or if it will make things easier in the long term. I CAN do this in a theme preprocess function. However, I've been using the twig extend functionality to leverage this module for other uses. Using "twig extend" from a new render template skips the pre-processing functions in the parent. Therefor, I would need a more universal preprocess or alter function which will run in more situations. – Kevin Nowaczyk Jan 22 '16 at 13:59
  • Does your module provide a new type of field? – Eyal Jan 22 '16 at 14:33
  • No field. It's a javascript library wrapper, so there's just code to look at what is being passed to drupalSettings and to the theme template, and then it decides which js files need to be attached. – Kevin Nowaczyk Jan 22 '16 at 15:32
  • I don't understand what you are trying to achieve. My suggestion is that you will look at the coffee from drupal code and try to find something similar. – Eyal Jan 22 '16 at 15:36
0

You can do it by this way

Step one

In function preprocess_theme() you need define variable is name libraries

<?php

function template_preprocess_FUNCTION_THEME(&$vars) {

    $vars['libraries'] = [];

    if ($vars['options']['xaxis']['mode'] == 'categories') {
        $vars['libraries'][] = 'categories';
    }

    if (isset($vars['options']['selection'])) {
        $vars['libraries'][] = 'selection';
    }

    if (isset($vars['options']['pan'])) {
        $vars['libraries'][] = 'navigate';  
    }

    if ($vars['resizable']) {
        $vars['libraries'][] = 'resize';    
    }
}

Step two In twig template add libraries

{% for library in libraries %}
    {% set library_name = 'flot_d8/' ~ library %}
    {{ attach_library(library_name) }}
{% endfor %}

{% if nodiv == false %}
    <div id="{{div_id}}" style="width:600px;height:300px;"></div>
{% endif %}

I think it's ok. About function hook_theme. Example i have function

function md_slider_theme($existing, $type, $theme, $path) {
  $theme = [];

  $theme['slider_edit_form'] = array(
    'variables' => array(
      'slid' => NULL,
      'settings' => NULL,
    ),
    'path' => $path . '/templates/backend',
  );

  $theme['admin_slides_render'] = array(
    'variables' => array(
      'slid' => NULL,
      'settings' => NULL,
      'slides' => NULL
    ),
    'path' => $path . '/templates/backend',
  );

  return $theme;
}

after hook_theme(). I have two function theme are slider_edit_form and admin_slider_render(). You can call function with array render example

$build = [
    '#theme' => 'slider_edit_form',
    '#slid' => $slid,
    '#settings' => $settings,
];

Html will define by template slider-edit-form.html.twig... .And every function theme have preprocess. Example

function template_proprocess_slider_edit_form(&$vars) {
    //process data is here
}
  • This leads in perfectly to my next step. The javascript FLOT library has many plug-ins provided by others that I would like to be able to add in if so desired. I'm guessing with this technique, I can create a new module for any plug-in, and have their preprocess hooks add more entries into the library array. This will allow multiple plugin modules to extend the flot_d8 module without overwriting each other, which is what would happen if I used the twig extend feature. – Kevin Nowaczyk Jan 21 '16 at 16:06
  • Attention for cache issues when using this approach. Make sure that final rendered entity will be unique otherwise can cause a cache hit and your libraries will not be loaded properly. – Vagner Jan 21 '16 at 16:44
  • If my module has a machine name of "flot_d8", what would I name this function; flot_d8_preprocess_theme(), template_preprocess_flot_d8_theme(), something else? I tried several names in my flot_d8.module file and nothing seems to work. – Kevin Nowaczyk Jan 21 '16 at 16:51
  • What's your funtion hook_theme? Function sugget your twig template? – MrD Jan 21 '16 at 17:13
  • The function flot_d8_theme() is the theme function which provides the list of twig templates which are included in my module. – Kevin Nowaczyk Jan 21 '16 at 17:16

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.