0

I have a custom module "jsblock." When the page renders, the module should get the title of the page, pass it to drupal_add_js() and ultimately render an output in a block.

I tested the module with the template name suggested by the system. The output rendered in the block as expected. Now, I'm trying to add a custom template to the module but the variable appears to no longer be passed to the block.

Directory structure

custom module directory structure

I have been playing around with hook_block_view() and a helper function to handle the drupal_add_js() function, but I think I am not attaching it to the block correctly.

jsblock.module file

// Helper

function get_the_page_title() {
  if ($node = menu_get_object('node')) {
    $title = drupal_get_title();
    drupal_add_js(array('jsblock' => array('test' => $title)), 'setting');
  }
}

// Theme
function jsblock_theme($existing, $type, $theme, $path){
  return array(
      'jsblock_custom_theme' => array(
          'variables' => array('content' => NULL),
          'template' => 'jsblock_custom_theme',
          'path' => drupal_get_path('module', 'jsblock') .'/theme/',
      )
  );
}

// Print
function jsblock_block_view($delta = 'jsblock') {
  if($delta == 'jsblock')
    {
      $block = array();
      $block['content'] = get_the_page_title();
      $block['content']['#attached']['css'][] = drupal_get_path("module", "jsblock")."/css/styles.css";
      $block['content'] = theme('jsblock_custom_theme');
      return $block;
  }
}

I checked the console for Drupal.settings.jsblock.test and it is returning the expected value. I can see the block is printing based on an expected outline, but the data is not rendered.

How can I pass the JS variable from the page to the block that uses a custom template?

1 Answer 1

1

When using a custom theme wrapper for your block output, you actually theme the content parts, before the block will be rendered using the actual block theme wrappers.

If you like to pass in variables to your custom template, you need to provide them via the second parameter of the theme() function:

/**
 * Implements hook_theme().
 */
function jsblock_theme($existing, $type, $theme, $path){
  return array(
    'jsblock_custom_theme' => array(
      'variables' => array('my_title' => NULL),
      'template' => 'jsblock_custom_theme',
      'path' => drupal_get_path('module', 'jsblock') .'/theme/',
    )
  );
}

/**
 * Implements hook_block_view().
 */
function jsblock_block_view($delta) {
  $block = array();

  if($delta == 'jsblock') {
    $variables = array();
    $variables['my_title'] = get_the_page_title();
    $block['content']['#markup'] = theme('jsblock_custom_theme', $variables);
    $block['content']['#attached']['css'][] = drupal_get_path('module', 'jsblock') . '/css/styles.css';
  }

  return $block;
}

Note the difference between the $variables and the $block array.

To also cover your second question (which surely should go into a separate question on Drupal Answers):

Keep in mind, that blocks are cached by default for performance reasons, until you clear the caches. So with your current implementation the block view will be generated only once and hence the JavaScript only attached to the first page you render after a cache clear.

Therefore you should attach your JS to the block output as you did with your CSS (attach it to the content part of the block output) and make sure to have a distinct cached version of the block for every page by using appropriate cache tags in your hook_block_info():

/**
 * Implements hook_block_info().
 */
function jsblock_block_info() {
  $blocks = array();

  $blocks['jsblock'] = array(
    'info' => t('My JS block'),
    // Use DRUPAL_NO_CACHE for no caching, or
    // DRUPAL_CACHE_PER_PAGE if you are fine with
    // cached versions per page.
    'cache' => DRUPAL_NO_CACHE,
  );

  return $blocks;
}
3
  • thanks for your answer! I updated my code to reflect your suggestions and now I am getting a WSOD and error Fatal error: Cannot use string offset as an array in modules\custom\jsblock\jsblock.module, referencing the function jsblock_block_view, specifically the line with the #attached css. Any idea what that might mean?
    – lane
    Commented Jan 9, 2018 at 1:32
  • 1
    @lcunning: Mea culpa. I didn't try the code myself. The theme function returns rendered output. So of course you have to use '#markup' as content render array element when you return the themed output with attached CSS or JS. See my above changes. Commented Jan 9, 2018 at 1:42
  • Nailed it. I want you to know how much I appreciate the time you take answering my questions. I've already learned a lot from you in the few questions you've helped me with.
    – lane
    Commented Jan 9, 2018 at 1:56

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.