0

I'm trying to add Javascript into a hook_entity_type_presave() hook, but it's not firing.

Is it possible to add within this hook?

I've attempted to with no success -- my code is below -- and this example on Drupal.org: https://www.drupal.org/docs/drupal-apis/javascript-api/add-javascript-to-your-theme-or-module ...describes the process of adding javascript within the context of two other custom modules, utilising hook_element_info_alter() and hook_page_attachments().

My module:

my_module
  my_module.libraries
  my_module.module
  my_module.info.yml
  js
    url-parameter.js

my_module.libraries:

url-parameter:
  version: 1.x  
  js:
    js/url-parameter.js: {}
  dependencies:
    - core/jquery

my_module.module


function my_module_node_presave(Drupal\node\NodeInterface $entity) {

  //other code related to the presave hook, which works fine

  //I attempt to load the JS here, but it's not firing:

  $attachments['#attached']['library'][] = 'js/url-parameter.js';
  
}

js\url-parameter.js:

(function (jQuery) {
  jQuery(document).ready(function() {
    alert("hello");
    console.log('Loaded');
  });
})(jQuery);

3
  • 1
    If you could update the question and describe in a bit more detail what your end goal is I think it would help - you can't attach JS in a presave hook (well you probably could, forcibly), but it doesn't really make sense to think about attaching it there anyway - your custom JS would surely only be applicable to certain pages/contexts, and there's no guarantee that page/context will be in scope every time the entity is saved. So it'd be good to know exactly what you want to happen
    – Clive
    Jul 31 at 19:26
  • Thanks @Clive . The purpose of the presave hook is to add a consistent hero image and text to certain types of nodes (i.e. a specific type of event page). Apologies, I removed that logic when attempting to simplify the code for this question. My thinking was: while I am adding the hero image and text, I'd also like to add a script to those same types of nodes. Adding the JS within the same hook would work but if you have a recommendation for a better approach, please send word. Jul 31 at 19:39
  • 1
    You probably want to think about separating that logic out - setting node data is definitely a job for the presave hook, but arguably the JS belongs to the node page, not to the save operation, so might be better conditionally attached to the node view instead. There's an example here: drupal.stackexchange.com/questions/231160/…, presumably you'd need to add some extra logic to check whether the hero fields are populated, and then attach the library
    – Clive
    Jul 31 at 19:43
3

hook_entity_presave() and hook_ENTITY_TYPE_presave() should not assume the entity has been edited using a form, or a page has been shown to the users. Those hooks are also invoked when an entity is programmatically created, for example with the following code, which could also be used in a hook_cron() implementation.

$values = [
  'type' => 'article',
  'title' => 'The article title',
  'uid' => 1,
  'status' => TRUE,
];
$node = \Drupal::entityManager()->getStorage('node')->create($values);
$node->save();

The hook invoked before an entity is rendered is hook_entity_view() (or hook_ENTITY_TYPE_view()). Using one of those hooks, a module can add an extra rendering array in $build, for example with $build['#attached']['library'][] = 'js/url-parameter.js';.

As the example code, $display->getComponent() should be used to verify the entity field has been set to be rendered, since administrator users can hide fields from /admin/structure/types/manage/article/display (for the Article content type). For example, with the following settings, I would hide a custom entity field and the Tags field for the Article content type.

screenshot

I would also check the value of $view_mode passed to those hooks as that value says why the node is rendered. For example, when the Search module indexes the nodes, $view_mode is equal to 'search_index'; when a node is added to a RSS feed, $view_mode is equal to 'rss'. In those cases, you probably don't want to add a library.

2
  • Thank you @apaderno, will attempt this approach, I think this will solve the issue. Aug 1 at 11:39
  • Just confirming, this helped me to address this issue. Thank you @apaderno Aug 3 at 11:05

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.