These extra items nestle in alongside fields on the node, so can be considered 'pseudo-fields', but on their own are totally inflexible as they can't be repositioned and seem to appear out of nowhere onto the page. You should give yourself or site owners/administrators as much power as possible to customize content - and there is an easy solution here, to allow your extra content to be repositioned in exactly the same way as standard fields in the manage fields/display UI can be.

Simply implement hook_field_extra_fields() in your custom module, and your pseudo-fields will appear alongside fields in those administrative screens like this:

You declare your pseudo-fields (or 'extra fields') to the Fields API so that it can check the rendered nodes for you and set the orders of fields and your extra content according to the field display settings rather than just the defaults that you hard-wired in code. You specify which entities and which bundles your pseudo-fields are attached to, and whether they are on the displayed content, or on the edit/create form for the type of content. For the FB Like example above, here's what we do:

/** * Implements hook_field_extra_fields(). * * Declare our Facebook Like button as a pseudo-field. */function MYMODULE_field_extra_fields() { // The levels of the array that we return correspond to the // entity type, bundle and then either 'display' or 'form'. // In this case, we apply to 'page' nodes, when we display them. $extra['node']['page']['display'] = array( // The keys here must correspond to the keys of the items // that we add in our hook_node_view() or similar function. // Prefix it with our module name to ensure it doesn't clash // with anything from other modules. 'MYMODULE_fb_like' => array( 'label' => t('Custom FB Like button'), 'description' => t('Facebook like button, added in MYMODULE_node_view().'), 'weight' => 10, ), ); return $extra;}

Some brief explanation of the parts you specify in the hook_field_extra_fields():

Either specify 'display' or 'form' depending on whether your extra content is shown on the displayed content (which is what we do in this example), or the create/edit forms of the content. Most of this article is talking about adding pseudo-fields to the display of content, but have a look at the Domain Access module as an example of an extra item on the form -- see domain_field_extra_fields() -- which it uses to add the domain settings for specific nodes.

The label is only what is shown in the manage fields/display settings screen, it is not used on the actual content.

The description doesn't seem to get used anywhere so is useful as documentation for anyone that reads your code. I would recommend referring to which function adds the pseudo-field to the content as that's not always obvious.

If you've added the hooks above to your own module, make sure you replace 'MYMODULE' with your own module name, and flush your site caches for Drupal to pick them up (or just enable the module).

Part of the joy of using hook_field_extra_fields is that it will work with other field management tools like Field Group. You can place your pseudo-fields within field groups painlessly this way. Here's an example (click the images to see them in full):

About the author

James Williams has been building Drupal websites for many years, he has a keen eye for detail and can look beyond the obvious and help our clients implement the features that they really want. He is a lead developer on many projects and is able to co-ordinate a team to deliver a project.

His growing list of specialisms include the Panels, Features and Views modules, internationalisation/translation and creative approaches to modelling content with Drupal.

James loves football, playing football, watching football, talking about football, playing football again and reading about football. Sometimes he thinks about football too much.

Comments

This is hugely helpful. I've been trying to marry my custom fields into the UI precisely to get them into Field Groups without having to set #group_children elements and such in hook_node_view(), which gets very messy very fast.

Do you know how to get this to also display the label as described in hook_field_extra_fields()? That would be the final piece to the puzzle for me.

That's awesome, I never thought of mixing form elements into my node's render arrays, but they certainly work just fine. Only problem with "item" is that I can't specify the label to display inline.

In response to your last point, I would think the label should be allowed to be displayed ("Display/Hidden" on the fields display page) since that allows the label to be hidden if it's for administrative purposes only.

Agreed! The label is only 'meant' to be administrative, but you can of course use it.
To make your label appear inline, you could try messing around with adding '#theme_wrappers' => 'field', '#label_display' => 'inline' (or something like that) to your render array but that's not so simple -- just add some theming for your specific label.
There's no in-built way to set the label display in the UI otherwise, since these custom elements we add may or may not have a label, the Fields UI just has no way of knowing.

Render arrays are awesome -- form elements are just render arrays, there's nothing special about them. I use them everywhere now - it keeps everything easily alterable :-)

Comments on this article are now closed, if you want to give us feeback you can use our contact form instead.