Theming
Topic

Render API: How to Output Content for Drupal 8, 9, 10, and 11

The Render API consists of two parts: structured arrays that provide data and hints about how that data should be rendered, and a rendering pipeline that can be used to render these arrays into various output formats. It is used for all content output for display by Drupal, as well as for describing and controlling forms that collect user input, and directing how that input is handled.

The Render API serves as the glue between modules which store and manipulate data on the backend, and themes that display that data to users. As such, it’s important for both theme and module developers to understand at least the basics of how the Render API works, the difference between elements and properties in a render array, and the concept of callback functions.

Example tasks

  • Define content, or forms, to be displayed in a module
  • Alter content, or a form, provided by another module
  • Discover which Twig template is used to theme an element in a render array
  • Alter existing render arrays in order to change the appearance of content when it is displayed

Confidence

We don’t anticipate any major changes to how the Render API works in the Drupal 8 cycle. Writing a render array hasn’t changed much between Drupal 7 and 8. The concepts like elements and properties are still the same, with the major difference being that render elements are now implemented as plugins.

Drupalize.Me resources

Drupal 8, 9, 10, and 11
More information

The Render API consists of two parts: structured arrays that provide data and hints about how that data should be rendered, and a rendering pipeline that can be used to render these arrays into various output formats. Understanding at least the basics of how the Render API works, the difference between elements and properties, and the concept of callback functions is an integral part of learning Drupal.

In this tutorial we'll:

  • Look at the fundamentals of the Drupal Render API
  • Point to additional material to provide more detail about the inner workings of the Render API and how content is output in Drupal
Drupal 8, 9, 10, and 11
More information

The core structure of Drupal's Render API is the render array, which is a hierarchical associative array containing data to be rendered and properties describing how the data should be rendered. As a module developer you'll use render arrays to describe the content your module controls in order to output it on a page as HTML, or as part of a response in another format like JSON. As a theme developer, you'll manipulate render arrays in order to affect the way content is output on the page.

In this tutorial we'll learn:

  • What render arrays are and why they exist
  • The basic format of a render array
  • What "properties" and "elements" signify in the context of a render array
  • Where to find more information about how to create a render array to describe your own content

By the end of this tutorial you should be able to understand when you need to use a render array, recognize one when you see it, and know where to get more detailed information about render array formatting specifics.

Drupal 8, 9, 10, and 11
More information

One of the central components of Drupal's Render API is render elements. You can think of them as prepackaged render arrays or shortcuts you can use to describe common things, like tables, links, and form elements, in a consistent way. In this tutorial we'll take a more in-depth look at the use of the #type property in render arrays in order to answer questions like:

  • What are render elements, and what is their use case?
  • Where can I find more information about available element types?

By the end of this tutorial you should be able to identify individual render element types within a larger render array, find the relevant documentation for specific types of render elements, and explain the use case for render elements.

More information

Strings of simple HTML and plain text can be defined in a render array using the #markup and #plain_text element types. In this tutorial we'll look at:

  • Adding simple strings to a render array so they appear as HTML on the page
  • When to use #markup and #plain_text in your code

By the end of this tutorial, you should be able to add simple strings of HTML and plain text to a render array.

More information

We often need to add code to an alter hook or preprocess function that adds additional HTML attributes to items in a render array. Maybe you're developing a module that adds conditional classes to elements on the page under certain circumstances. Or perhaps your theme needs to add some data attributes to certain links, or form elements, in order to enable some custom JavaScript functionality.

Adding HTML attributes like class, id, or data-* to render array elements involves:

  • Adding the desired values to the element in a render array as an array of key/value pairs
  • Converting the values in the render array to an Attribute object
  • Outputting the Attribute object inside a template file

In this tutorial, we'll cover all of these steps. By the end of this tutorial, you should be able to add new HTML attributes to elements in a render array and discover which property those values should be added to, depending on the element in question.

Categories
Drupal 8, 9, 10, and 11
More information

Drupal makes it easy to convert an array of strings to an ordered or unordered HTML list using '#theme' => 'item_list' elements in a render array. This is commonly done by module developers to display a list such as links to content, the values of settings in a module, or the names of everyone who has viewed a page. Displaying lists is a super common task for a content management system.

In this tutorial we'll look at:

  • Outputting an array of items as an unordered <ul> list
  • Properties specific to '#theme' => 'item_list' in a render array

By the end of this tutorial you should be able to output unordered lists.

Categories
Drupal 8, 9, 10, and 11
More information

The #table render element type is a powerful way to output an array of rows and columns as an HTML table. It supports all the features of a standard HTML <table> element like headers, captions, and column groups. Data to be displayed in the table can be an array of simple string values, or an array of render arrays where each sub element is a row with columns as child elements. In addition, when used in the context of a form, tables can be made into a multiple select widget, or have drag-and-drop reordering of rows enabled. Whether you just want to display a set of tabular data, or you provide your users with a complex form element for reordering and nesting items inside a menu tree, it can all be done with the #table element.

In this tutorial we'll:

  • Look at outputting simple strings as a table
  • Provide definitions for all the various properties that can be used to define a table element
  • Demonstrate how to use the #tableselect and #tabledrag options to create complex form widgets

By the end of this tutorial you should be able to create HTML tables in all their various permutations as part of a render array.

More information

#prefix and #suffix are two commonly used examples of standard properties. That is, they are available for use on any element in a render array regardless of the element #type or #theme property's value. They are a great way to add additional layout markup to an element in a theme-agnostic way.

In this tutorial we'll:

  • Use the #prefix and #suffix Render API properties to wrap an element
  • Look at some possible use cases for using #prefix and #suffix in your own code

By the end of this tutorial you should know how, and when, to use the #prefix and #suffix properties in a render array.

More information

In this tutorial we'll look at how you can use the #theme property of a render array to define custom HTML. With this information, module developers can use render arrays to define content, and theme developers can understand how elements in a render array are converted to HTML and which templates they can override to change the output for a specific element.

Learn how to:

  • Use hook_theme() to define a new theme hook and define default values for variables
  • Create a corresponding Twig template file that outputs the variables and any custom HTML markup
  • Use a preprocess function to add additional variables for the Twig template file you created
  • Use the new theme hook in conjunction with a #theme property in a render array to link your Twig template file to actual content

By the end of this tutorial you should know how to define new templates to output content as HTML. You should also have a better understanding of how Twig template files are linked to elements in a render array.

More information

There are a bunch of existing render elements, most commonly Form API elements. You need to know how to discover and make use of existing elements. In this tutorial, we'll learn how to:

  • Locate a list of elements provided by Drupal core
  • Figure out what properties apply to each element
  • Use any render element type when defining content or forms in our code

By the end of this tutorial you should know what render element types are available for you to use, and how to find the details you'll need in order to implement them in your own render arrays.

More information

The #access property can be used with any element in a render array, including form elements, to control the visibility of that element and its children. This is an effective way to limit access to specific parts of a page's content to only those users with the required permissions, and to show or hide material based on other conditional logic.

In this tutorial we'll:

  • Review the #access Render API property
  • Demonstrate using the #access property to show/hide a field on a node depending on the current user's permissions

By the end of this tutorial you should be able to limit access to any element on the page via logic that returns a Boolean value.

Categories
Drupal 8, 9, 10, and 11
More information

The individual items that make up the content of a page impact the cacheability of that page. In order for Drupal's cache and external caches to better understand how the content varies on a page, module developers use the #cache render element property. The #cache property defines cacheability metadata for individual elements in a render array.

Additionally, these Render API elements can become fairly complex. The calculation of what the final HTML output should look like often involves looking up content in the database, checking multiple conditions, maybe querying an external API, and various other tasks. This can cause turning a render array into HTML to become quite expensive. In order to speed up this process, the Render API will cache the generated HTML for each element and reuse it on future requests whenever possible -- but only if you tell it to do so.

In this tutorial, we'll look at:

  • How render caching impacts the performance of a page
  • Defining the cacheability of an item with cache tags, cache contexts, and cache max-age
  • Examples of using the #cache property in a render array

By the end of this tutorial you should know how, and when, to use the #cache property when defining render arrays.

Categories
Drupal 8, 9, 10, and 11
More information

Some Render API properties, like #pre_render, #element_validate, and #lazy_builder are considered callable. Rather than receiving a static value, they contain a pointer to code that should be called at a specific time during the process of rendering a render element. Callbacks are used in some cases to return a value that can be substituted into the render array, and in other cases given the opportunity to manipulate the current element in the array directly.

In this tutorial, we'll:

  • Look at what callbacks are
  • List some common callback properties
  • Show various ways that callback code can be defined
  • Discuss how to choose which method to use

By the end of this tutorial, you should be able to define an appropriate value for any Render API property that expects a callback, and define the logic that is executed when the callback is triggered.

Categories
Drupal 8, 9, 10, and 11
More information

The Render API is capable of detecting poorly-cacheable (highly dynamic) parts of a page and rendering them later using a process called auto-placeholdering. This works by using #lazy_builder callbacks to lazy load certain very dynamic subtrees of a render array. The place in the array where that very dynamic content would appear is first assigned a placeholder. At the very last moment it is replaced with the actual content.

This allows Drupal to do things like cache the overall page in the Dynamic Page Cache despite parts of the page being too dynamic to be worth caching. It also allows the Render API to assemble a page using cache fragments combined with non-cacheable elements.

In this tutorial we'll:

  • Discuss what lazy builders are and how they work in conjunction with placeholders to speed up the rendering pipeline
  • Cover some common gotchas for lazy builders
  • Look at some example code that implements a lazy builder callback

By the end of this tutorial, you should know how and when to use the #lazy_builder property of a render array and how Drupal uses placeholders to increase the cacheability of content and speed up the rendering process.

Categories
Drupal 8, 9, 10, and 11
More information

This tutorial looks at the steps that Drupal goes through to obtain a render array for an incoming HTTP request, transform the render array into HTML, and then return it to your browser. We provide an outline of the process and links to resources for more in-depth information. We also take a more thorough look at the HtmlRenderer which converts a render array into HTML. Knowing how the render arrays you write in your code are ultimately used can help you optimize Drupal's Render API to describe your module's content.

Categories
Drupal 8, 9, 10, and 11
More information

Modules can provide new render element types -- a powerful way to encapsulate complex logic into a reusable component. This can help to cut down on code repetition, and allow other module developers to build on your work. In this tutorial we'll:

  • Define a recipe for creating a new render element type
  • Look at the code for the marquee element type from the render_example module in the Examples for Developers project.

By the end of this tutorial you should be able to implement a new render element type in your own module and make use of it when defining content as part of a render array.

Categories
Drupal 8, 9, 10, and 11
More information

Linking to things is probably one of the first things you learned how to do as a web developer. Anchor tags are the framework of how the world wide web works. So it's important to know how to create them in Drupal. Chances are you'll be doing a lot of it.

Creating links to things in Drupal, however, is a bit more complicated than just typing out an HTML anchor tag. It requires understanding how URLs are generated from routes, and how to define links as renderable arrays. It can also be tricky because of the multitude of deprecated, but still functioning, ways of creating links.

In this tutorial we'll:

  • Use the \Drupal\Core\Url class to generate URL objects from routes and external URIs.
  • Use the \Drupal\Core\Link class to create HTML links within a Drupal module.
  • Examine best practices for working with URLs and links in a Drupal module in order to ensure that your code continues to work into the future.

By the end of this tutorial you should be able to link to anything, either internal to your application or external, using Drupal best practices.

Categories
Drupal 8, 9, 10, and 11
More information

Renderers are the services that take a render array and convert it to HTML (or JSON, or any other format). As a module developer, understanding how they work will help you gain a better understanding of what happens behind the scenes when Drupal links an incoming request to your custom controller and then handles the data you return.

In this tutorial we'll:

  • Define renderers
  • List the renderers available in Drupal core
  • Demonstrate how you can create a link that forces the use of a different renderer

By the end of this tutorial, you should understand the role that renderers play in the Drupal render pipeline and when you might want to use one other than the default.

Categories
Drupal 7, 8, 9, 10, and 11
More information

Drupal provides a standard, secured method for module developers to add forms to a Drupal website. Learn how to use the Form API to build, validate, and submit a custom form.

Categories
Drupal 8, 9, 10, and 11
More information

Many of the processes that Drupal performs when responding to a request are cached in order to increase performance. Creating the HTML for the page that a user sees or the JSON response to a REST request can require thousands of operations. Some operations are time consuming, memory heavy, CPU intense, or all 3. By performing the operation once, and then caching the result for next time, subsequent requests can be fulfilled faster. In order to make it easier to store, retrieve, and invalidate cached data, Drupal provides cache-related services you can use in your code. Drupal also enables you to provide information about the cacheability of data to the Render API to improve the performance of page rendering.

In this tutorial we'll:

  • Cover the terms and concepts you should be familiar with when working with the Cache API
  • Point to additional resources for more information about how to perform specific tasks with the Cache API

By the end of this tutorial, you should be able to define the concepts of bubbling and cache invalidation, and know how cache keys, tags, context, and max-age are used to provide cacheability metadata for items.

Categories
Drupal 8, 9, 10, and 11
More information

The individual items that make up the content of a page impact the cacheability of that page. In order for Drupal's cache and external caches to better understand how the content varies on a page, module developers use the #cache render element property. The #cache property defines cacheability metadata for individual elements in a render array.

Additionally, these Render API elements can become fairly complex. The calculation of what the final HTML output should look like often involves looking up content in the database, checking multiple conditions, maybe querying an external API, and various other tasks. This can cause turning a render array into HTML to become quite expensive. In order to speed up this process, the Render API will cache the generated HTML for each element and reuse it on future requests whenever possible -- but only if you tell it to do so.

In this tutorial, we'll look at:

  • How render caching impacts the performance of a page
  • Defining the cacheability of an item with cache tags, cache contexts, and cache max-age
  • Examples of using the #cache property in a render array

By the end of this tutorial you should know how, and when, to use the #cache property when defining render arrays.

Guides

Not sure where to start? Our guides provide useful learning tracks for all skill levels.

Navigate guides

External resources

  • A code-level Render API overview (api.drupal.org)
    • Overview of the Theme system and Render API.
  • Render API (Drupal.org)
    • Documentation that goes into more depth on specific aspects of the Render API. Useful for understanding how these more complex parts work.
  • Examples for Developers (Drupal.org)
    • The Examples project contains a Form API and a Render API example, both of which provide code samples that demonstrate the Render API in action.
  • Form and render elements (api.drupal.org)
    • Comprehensive list of all core render elements.
  • Aha! Understanding and Using Render Arrays in Drupal 8 (events.drupal.org)
  • Presentation from DrupalCon NOLA that provides a good overview of the Render API, its use case, and a little history.
  • The Drupal 8 render pipeline (Drupal.org)
    • An in-depth look at Drupal’s request handling and rendering flow. Contains a helpful diagram linking all the pieces together.