2

I'm building a custom module (say 'mycalc') with a custom block with a custom form inside. Now I want to attach a library to the form and add some styling and live manipulation.

I created the mycalc.libraries.yml like this:

myform:
  version: 1.x
  css:
    theme:
      css/mycalc.css: {}
  js:
    js/mycalc.js: {}
  dependencies:
    - core/jquery

I added the js/mycalc.js and css/mycalc.css files with few basic lines. Then in the src/Form/MyCalcForm.php (where is set the MyCalcForm class), i edited the buildForm method adding this just before the return():

$form['#attached']['library'][] = 'mycalc/myform';

But there's no js nor css loading. What's wrong? Please help!

2
  • 1
    First things first, did you clear the cache?
    – Kevin
    Jan 20, 2018 at 17:55
  • 1
    @Kevin Yes, of course. Both with drush cr and via web interface. Feb 21, 2018 at 11:27

1 Answer 1

11

First of all check for typos since, after failing to clear the cache is the most common mistake in this use case. After that, depending on your form base class attaching the library on the ::buildForm() method should suffice. Also worth noting that perhaps another module (custom or contrib) could be messing with your form render array.

In the case you need to attach library to a form from core or third-party, you need to implement a hook_form_alter():

/**
 * Implements hook_form_alter().
 */
function <YOUR_MODULE_NAME>_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id){
    // If your library is intended to be used on specific form
    // check for it using the $form_id argument against your
    // form id which in most cases is returned by the ::getFormId()
    // method of your form.
    if ($form_id !== '<YOUR_FORM_ID'>) {
        // This is called eager return, is a technique
        // to avoid code nesting to improve code readability.
        return;
    }
    // To attach Blazy for example.
    $form['#attached']['library'][] = 'blazy/load';
    // To attach a library from a theme.
    $form['#attached']['library'][] = '<YOUR_THEME_NAME>/<library_name>';
    // To attach a library from a module.
    $form['#attached']['library'][] = '<YOUR_MODULE_NAME>/<library_name>';
    // Pass even variable from this function to JS settings
    $form['#attached']['drupalSettings']['<YOUR_MODULE_NAME>']['variable'] = 'PHP Value To JS';

    return $form;
}

If you pass variable with above mentioned method - $form['#attached']['drupalSettings']['<YOUR.... then that variable will be available in your JS file.

(function ($, Drupal) {
  'use strict';

  Drupal.behaviors.<YOUR_MODULE_NAME> = {
    attach: function (context, settings) {  
       console.log(settings);
       console.log(settings.variable); //Should log variable value
    }
  };
})(jQuery, Drupal);

Add javascript to form by module

4
  • Also consider using hook_page_attachments_alter instead of form alter, it's made for this purpose
    – wranvaud
    Jan 9, 2022 at 13:52
  • Using hook_page_attachments_alter is overkill for this purpose, it's better attach the library where it's needed. Also using hook_form_alter ensures no matter what page your webform is, your library will be included and avoid attach it on those the form won't be.
    – d70rr3s
    Nov 14, 2022 at 9:36
  • The answer is missing the check for the $form_id, the current answer attaches the library for all forms on the site and could lead to unexpected behaviors.
    – d70rr3s
    Nov 14, 2022 at 9:39
  • In the JS, the second log line should be: console.log(settings.<YOUR_MODULE_NAME>.variable); Jan 26, 2023 at 4:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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