3

I'm updating this question on the suggestion of the initial provided answer.

When trying to render out the content of my custom field, outputting the data into a custom theming function to render on to the page when using the suggested method is resulting in the theming function being ignored, even when attempting to output just static strings of text or using the devel module to test it, nothing happens, the code is updated as below

/**
 * Implements hook_field_formatter_view().
 */
function mymodule_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array();
  foreach ($items as $delta => $item) {
    if ($file = file_load($item['image'])) {
      list($hours, $mins, $secs) = explode(':', $item['time']);
      $time = ((3600 * $hours) + (60 * $mins) + $secs);
      $element[$delta] = array(
        '#theme' => 'mymodule_formatter',
        '#image' => (array) $file,
        '#time' => $time,
        '#comment' => $item['comment'],
      );
    }
  }
return $element;
}

Hook and Theming function

/**
 * Implements hook_theme().
 */
function mymodule_theme() {
  return array(
    'mymodule_formatter' => array(
      'variables' => array('variables' => array()),
      'file' => 'theme_mymodule.inc',
    ),
  );
}

In the theme_mymodule.inc file

/**
 * Returns HTML for a MyModule.
 */
function theme_mymodule_formatter($variables) {
  $output = t('test');

  return $output;
}

I think I'm a little confused about the naming of the theme hook, when I was copying the image module, the #theme variable was just declared as 'image_formatter' but the function named was 'theme_image_formatter', I'm wondering if I've declared my theme hook wrong.

--Previous question--

Im trying to write my own custom field in my own module, I've written the field setup, and it's accepting and evaluating data fine, that's all good. I'm struggling to grasp what I need to do when trying to write my own theming output function. As an example to the parts of code I'm working on:

/**
 * Implements hook_field_formatter_view().
 */
function mymodule_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array();
  foreach ($items as $delta => $item) {
    if ($file = file_load($item['image'])) {
      list($hours, $mins, $secs) = explode(':', $item['time']);
      $time = ((3600 * $hours) + (60 * $mins) + $secs);
      $variables = array(
        'image' => (array) $file,
        'time' => $time,
        'comment' => $item['comment'],
      );
      $element[$delta] = theme('mymodule_formatter', $variables);
    }
  }
return $element;
}

And my theming function

/**
 * Returns HTML for a MyModule.
 */
function theme_mymodule_formatter($variables) {
  $item = $variables['image'];
  $image = array(
    'path' => $item['uri'],
  );

  if (isset($item['attributes'])) {
    $image['attributes'] = $item['attributes'];
  }

  if (isset($variables['image_style'])) {
    $image['style_name'] = $variables['image_style'];
    $output = theme('image_style', $image);
  }
  else {
    $output = theme('image', $image);
  }

  return $output;
}

Now this returns the correct HTML for my image, so it actually returns a string like

<img typeof="foaf:Image" src="[img_path]" width="120" height="90" alt="" />

However this doesn't actually render on my page, it doesn't come back with an error, it just doesn't show anything.

When I change my $element[$delta] line in my hook_field_formatter_view() function to say

$element[$delta] = array('#markup' => theme('mymodule_formatter', $variables));

By putting the element into a '#markup' array, it does actually render the image, however I don't want to just throw everything into a '#markup' array if that's not the proper way of doing it.

2

To add markup that's already been prepared to a render array, you would indeed use #markup. There's nothing wrong with using it where appropriate.

However, since you're preparing the markup in the same function anyway, you may as well use the render array version of the call to theme(), e.g.

$element[$delta] = array(
  '#theme' => 'mymodule_formatter',
  '#image' => $image,
  '#another_var' => 'foo',
);

It provides better structure, makes it easier for other modules to alter if necessary, and is better for caching.

  • That was the format the image module was written, so that was what I initially tried to mimic, however I've just tried using that method and it doesn't appear to be picking up my theme function anymore, even why I try to just output test text, it's not noticing the theme_mymodule_formatter function anymore – Andrew Morris Oct 7 '14 at 11:49
  • That snippet should be more or less identical to $element[$delta]['#markup'] = theme('mymodule_formatter', $variables);...if one works the other should too. Might be an idea to update the question with the code you're using now, maybe there have been other modifications? – Clive Oct 7 '14 at 11:57
  • Ok, i'll edit the question and the title shortly – Andrew Morris Oct 7 '14 at 12:28
0

Right I've managed to work it out, I've done some additional reading on the render array information Clive posted in his answer, and followed the examples module slightly to realise what I'd done wrong. I'll mark the other answer as correct because what I actually wanted to know was what the correct method was for outputting the data

My problem was with this data

/**
 * Implements hook_theme().
 */
function mymodule_theme() {
  return array(
    'mymodule_formatter' => array(
      'variables' => array('variables' => array()),
      'file' => 'theme_mymodule.inc',
    ),
  );
}

Declaring the array in this way means the function is expecting an array called 'variables' as it's only parameter, so you need to declare any parameter it will receive first, so that they can then be passed properly.

/**
 * Implements hook_theme().
 */
function mymodule_theme() {
  return array(
    'mymodule_formatter' => array(
      'variables' => array(
        'image' => NULL,
        'comment' => NULL,
        'time' => NULL,
      ),
    ),
  );
}

Anyone having similar troubles I would suggest reading the 'render arrays' link in the other answer, and following the information in that.

0

Having never read properly about render arrays one issue related to this was driving crazy.

My theme function was receiving null values in the $variable arguments. This was my formatter view:

function my_videotype_field_formatter_view ($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $element = [];
  $settings = $display['settings'];
  foreach ($items as $delta => $item) {
    $element[$delta] = [
      '#theme' => 'my_video_player',
      '#item' => $item,
      '#settings' => $settings,
      '#entity_type' => $entity_type,
      '#entity' => $entity,
    ];
  }
  return $element;
}

And my theme declaration:

function my_videotype_theme ($existing, $type, $theme, $path) {
  $theme = [];
  $theme['my_video_player'] = [
    'variables' => [
      '#item' => NULL,
      '#settings' => [],
      '#entity_type' => NULL,
      '#entity' => NULL,
    ],
    'file' => 'includes/my_video.theme.inc',
  ];
  return $theme;
}

As it turns out (after reading this thread) the hash is actually important... so vars are passed with hash to signal they are data in render arrays, but are actually stripped of the hash to evaluate... (hard to explain). So the theme declaration expects variables=>[item=>value] not variables=>[item=>#value] as declared in the render array. Thus the correct theme declaration would be:

function my_videotype_theme ($existing, $type, $theme, $path) {
      $theme = [];
      $theme['my_video_player'] = [
        'variables' => [
          'item' => NULL,
          'settings' => [],
          'entity_type' => NULL,
          'entity' => NULL,
        ],
        'file' => 'includes/my_video.theme.inc',
      ];
      return $theme;
    }

The other strange thing is that when calling theme through function, not render array:

$u=theme('my_video_player',['#item'=>$item,'#settings' => $settings]);

It would work even with the hash on the theme declaration... confusing.

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.