Score:0

Adding Javascript within a hook_entity_type_presave() hook

es flag

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);

cn flag
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
scaffolding avatar
es flag
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.
cn flag
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: https://drupal.stackexchange.com/questions/231160/attach-javascript-library-and-settings-to-a-node-page, presumably you'd need to add some extra logic to check whether the hero fields are populated, and then attach the library
Score:3
us flag

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.

scaffolding avatar
es flag
Thank you @apaderno, will attempt this approach, I think this will solve the issue.
scaffolding avatar
es flag
Just confirming, this helped me to address this issue. Thank you @apaderno
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.