Adding a custom widget inside a node using hook_node_view

In this tutorial, we will see how we can create our custom widget using drupal’s hook_theme and then add into Drupal’s $content available in the node tpl. The main aim is to get the widget across all the content type without adding any code to the tpl.

In this tutorial, I will show you how we can use the hook_node_view to add a custom widget to render directly in the node without changing or modifying anything in the node tpl. The best thing about this approach is when we want some elements common to all the content type. Yes, we can add the element by adding that in the node tpl. But there is better approach and this is one of them.

You can check my previous tutorial where I have shown how we can add the like dislike element to the node tpl using hook_node_load. But the problem with that approach is when we have a lot of content types; we have to add them to all the tpls.

So here is the list of thing that we are going to do:

  1. Create a view where we will pass tags as arguments and get a list of 4 articles as related links.
  2. Use the hook to get our widget in $content as $content[‘relatedlinks’].
  3. Customize the tpl for the widget as per our requirement (not the node tpl).

So, let’s dive in.

Creating the view

Nothing great done to this view. The Format is getting to grid view and I am displaying three fields i.e. the Taxonomy term “Tag”, the image field “Image” and the “Title” of the article. I have added a relationship Content: Tag to get the name of the tag and passed the tag’s id in argument by adding the contextual filter. Check the export code of the view if you find any problem doing it yourself, but it’s very basic stuff. And yes, in the query setting I have selected to have distinct values so that the nodes are not repeated by any change.

Hampi

Hook to get the widget

Time to get on with our favourite text editor and start writing some code. The first is writing out hook_theme where we will define our tpl and the variables. Here is the code:

function nodecontent_theme($existing, $type, $theme, $path) {
  return array(
    'relatedlinks' => array(
      'template' => 'templates/relatedlinks',
      'variables' => array('viewresult' => NULL, 'tags' => NULL),
    ),
  );
}

Then we write the hook_node_view where we will specify the content of related links and that it should be visible only in “full” node view.

function nodecontent_node_view($node, $view_mode, $langcode) {
  if ($view_mode == 'full') {
    $node->content['relatedlinks'] = nodecontent_get_related_links($node->field_tags,$node->language);
  }
}

Inside the hook_node_view I have called a function nodecontent_get_related_links where I have passed the array of tags field and the language of the node which is very much required to iterate through the field array. The main thing is to iterate through the array and create a string and concatenate the plus sign in $argument and used the substring function to remove the last plus sign which will come as an extra character. So, the final argument will become something like 1+2+3. This is passed into the views_embed_view function as an argument which we have created at the first step.

function nodecontent_get_related_links($tags,$language) {
  
  $argument = '';
  foreach ($tags[$language] as $key => $value) {
    $argument .= $value['tid'] . '+'; // Adding the ids as string with '+'
  }
  
  $argument = substr($argument, 0,-1); // Removing the last '+' sign.
  
  $output = array(
    '#theme' => 'relatedlinks',
    '#viewresult' => views_embed_view('related_links','block',$argument),
    '#tags' => $tags,
  );
  
  return $output;
}

After that, we print $viewresult in the tpl which is coming from the nodecontent_get_related_links where we are defining the same in $output. And we also added the title related links inside an H3 tag to make it look obvious.

<h3><em><u>Related Links:</u></em></h3>
 
<?php print ($viewresult); ?>

Yeah, that’s about it. I don’t have to insert anything in the tpl or write any logic. If in any case we need to modify the position, we can play around with the weight of the widget, but generally it will come as the last element and before the links which are rendered after content (check the node.tpl) of your theme.

You can get the code here @ github: Code