1

I am hoping that this enquiry will be a easy one for someone to help shed some light on... I know that in order to create a textarea in Drupal 8 the following code can be used (e.g. render array)

$the_textarea=array(
        '#type' => 'textarea',
        '#required' => FALSE,
        '#ajax' => array (
            // Function to call when event on form element triggered.
            'callback' => array($this->componentCallbackObject,$this->componentCallbackFunction),
            'event' => $this->componentEvent,
        ),
    );

In the above code, a callback is defined using ajax ... this has the result of the code requiring the client to communicate with the server, which then sends back instructions to the client side using ajax... Is there away to get a component to execute some javascript (where the javascript would be loaded when the page in question, first loads) and when either the upkey, downkey or onchange event is triggered for the textarea the javascript, which would already be available to the client would be executed.

The main point here is that the client wouldn't need to communicate with the server, just with the javascript which is loaded when the page first loads e.g. without having to callback to the server and then wait for the server to send back the information.

2 Answers 2

1

The technique you need is easy, the full details can be complicated (depending on exactly what you want the JS to do). You can attach a custom JavaScript file from without your module in three steps:

  1. Create the JS file.
  2. Define a library.
  3. Attach the library to the form element.

The JavaScript should typically live in a folder named js at the root of your module: js/my-great-jscode.js.

To create your library add a [module_name].libraries.yml file to the root of your custom module. In there define the library:

my-library:
  version: 1.x
  js:
    js/my-great-jscode.js: {}

Then to attach the code to your form element you add #attached => library to the render array.

$the_textarea=array(
  '#type' => 'textarea',
  '#required' => FALSE,
  '#ajax' => array (
  // Function to call when event on form element triggered.
  'callback' => array($this->componentCallbackObject,$this->componentCallbackFunction),
  'event' => $this->componentEvent,
  ),
  '#attached' => [
    'library' => [
      'my-module/my-library',
    ],
  ],
);

There is more detail in Adding stylesheets (CSS) and JavaScript (JS) to a Drupal 8 module on Drupal.org

2
  • @crosman thanks for the info definitely helpful and much appreciated ... to touch on second element of the query would the only way to assign an action to the element (e.g. textarea say on a key press) be jQuery("#edit-test-textarea").on( "keydown", function() { alert("texted area key down."); }); or is there potential to use something like the <a href="#" onkeypress="function ()"> e.g. non-jquery to assign event related actions
    – Mo-ster
    Nov 29, 2016 at 14:44
  • You can do that through other mechanisms (that require a bit more hoop-jumping), but generally I try to do things through the Drupal mechanisms when possible so it consistent with other parts of the site. I always recommend you embrace and leverage the platform you're using.
    – acrosman
    Nov 29, 2016 at 16:42
0

The main point here is that the client wouldn't need to communicate with the server, just with the javascript which is loaded when the page first loads e.g. without having to callback to the server and then wait for the server to send back the information.

That is not AJAx, that's just plain javascript. So you shouldn't use the #ajax system for if that's not what you want. Keep in mind that using ajax is a must if you need to change the form, because Drupal will not accept form elements that it didn't provide.

There's also the #states API, see https://randyfay.com/states. It allows some basic client-side changes, like making form elements visible based on another element/selection, showing them as required (note that you still need to do server-side validation yourself too) and so on.

And if that's not enough, then sure, you can always write your own JS, add that using libraries.yml and #attached and do whatever you want there. You might also need to look into using drupalSettings to dynamically pass configuration (like the name of your form element if it is not hardcoded) to your JS, so it knows what to do.

3
  • Thanks for taking the time to answer, and bringing the #states functionality to my attention (a plus) and highlighting the need to use AJAX if elements are added to the form in a manner that Drupal needs to be able to see (e.g. be aware of)... I wondered whether you might be able to shed some light on the second element of the question, namely assigning javascript to execute on a given event e.g. in this example, for a textarea when it is updated or a key pushed for it; is the only way through utilising jquery e.g. jQuery("#textarea").on( "keyup", function() {alert("key up.");});
    – Mo-ster
    Nov 29, 2016 at 14:36
  • What would be wrong with using jQuery()? If you want javascript-only logic that doesn't require a server roundtrip, then writing JS is exactly what you should do then. Nothing wrong with that. You'll find a lot of JS in modules to add additional functionality.
    – Berdir
    Nov 29, 2016 at 21:06
  • I guess when I started out I wasn't thinking of using jquery, so was wondering how to get the "on" attribute to be defined in the render array and then just point to the javascript function in question... rather than pointing to the javascript function in a manner suggested by acrosman and then using $('{element}').on(function) to add the "on" action etc hence I was just wondering whether that was possible through the render array. Thanks for your help
    – Mo-ster
    Dec 1, 2016 at 17:48

Your Answer

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

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