Manipulating the Output of Render Elements
As mentioned, having a structured array to work with is far more flexible than a bunch of HTML. This allows you to make only the changes you want to make with ease, whether big or small, without having to re-write code from scratch.
The prospect of using render arrays to generate markup and using alter hooks in general are completely new concepts to Drupal theme developers. It’s very different than what you are used to, in a good way, but it takes some getting used to. In a lot of ways it’s easier than creating templates and theme functions for one-off implementations. The biggest issues front-end developers face when using the Render API are:
- Thinking about generating markup differently.
- Figuring out how to modify the content of a render array.
- Getting comfortable with implementing alter hooks.
Unlike theme hooks, render arrays are modified using alter hooks, not preprocess functions and templates. This can be confusing at first because render arrays are similar to theme hooks in that their purpose is to ultimately generate HTML markup, and they use templates and theme functions to do so. With render arrays, the
#theme property, which allows you to define which theme function or template should be used to render the element, is just one of many properties used and can be changed at any time. In general, you’ll use templates and theme functions to modify the markup itself, and you’ll use alter hooks to modify contents, structure, or placement of the elements before it’s rendered.
The following sections contain a few examples of things you can do with render arrays.
Generate New Content on the Fly
Generating new content is as simple as adding a new element to the page array. Listing 16–14 shows the addition of a new element called “new_stuff” to the pre-existing Highlighted region by implementing
hook_page_alter() in a theme’s
The first thing you did was name your new element “new_stuff,” gave it a
#type of container, and defined a class attribute of my-container. Note that container is an element, defined in
system_element_info(), which uses the
theme_container() theme function as a theme wrapper by default. This means the children of your element (heading and list) will be run through
theme_container(). The resulting markup is shown in Listing 16–15.
Then you added a subelement called “heading” and specified the
#type element property as
html_tag. This will cause the element to use
theme_html_tag() when rendering. You also specified
#attributes properties. These are parameters of the
theme_html_tag() function as you can see at http://api.drupal.org/api/function/theme_html_tag/7. The resulting markup is shown in Listing 16–16.
Finally, you added a subelement called “list.” Here you specified
item_list as the
#theme property and included an array containing your
#items, which is a required parameter for
theme_item_list(). The resulting markup is shown in Listing 16–17.
Move Content from One Region to Another
hook_page_alter() implementation, you can move the content of regions around at will. Listing 16–19 contains a few simple lines of code that move the contents of the entire first sidebar to the second sidebar, which results in the layout changing from a left sidebar layout to a right sidebar layout on full node pages. In Listing 16–19, you’ve also moved the breadcrumbs to the bottom of the footer region.
Altering Content Inside a Render Array
Altering the contents of a render array to change bits and pieces of the actual content is where you get into a very gray area. It could be argued that a change like this belongs inside a module. When making changes like this, it’s important to ask yourself whether or not the changes you are making should still apply when the theme you are developing is not active. Listing 16–20 changes the "View" and "Edit" tabs to read "Profile" and "Edit profile" on user profile pages.