Field formatters are responsible for taking the data stored by a field and transforming it into what a vistor sees. We can define new field formatters to output data for new field types or to provide alternative formatting options for existing field types. Creating a field formatter plugin is a common task for Drupal developers.
In this tutorial we'll:
- Define a new background color field formatter that uses the string stored by our field_example_rgb field type as the background color of the output.
- Make it possible for site builders to toggle on or off a feature that automatically adjusts the foreground text color of the output.
By the end of this tutorial you should be able to define a new custom field formatter plugin with settings that a site administrator can configure.
Field API Overview
FreeIf you've ever created or edited a piece of content on a Drupal site you have already interacted with the Field API. The Field module (along with its user interface counterpart) is responsible for providing the forms and data components used to build up the content model that make up a Drupal site. Understanding how Drupal fields work and how they're constructed via the Field API is an important part of understanding how Drupal works.
In this tutorial, we're going to look at the main components that make up the Field API at a high level. We'll see how the Field UI module exposes the field types included in core. We'll also look at the three main pieces that compose fields: types, widgets and formatters.
Drupal's Field API specifies the implementation details for field types, widgets and formatters. It also provides several hooks that allow custom code to alter these implementation details. In this tutorial we'll take a look at these Field API hooks and see how they can be used to change field types, widgets and formatters.
By the end of this lesson, you should be able to:
- Idenfity existing Field API hooks for manipulating field behavior
- Understand the proper method for changing the behavior of a field type, widget or formatter
- Know where to find the documentation for these API functions, and how to find their implementations
Of the 3 main components of the field system -- types, widgets and formatters -- only 1 has an impact on the actual display of content for end users: field formatters. Field formatters are responsible for taking the data stored by a field and transforming it into the markup that is sent to the browser when an end user views your site.
In this tutorial we'll:
- Look at the role field formatters play in the Field API
- Identify the main components that make up a field formatter
By the end of this tutorial you should be able to define the role of a field formatter plugin.
Drupal's field system provides us with a flexible system of adding different types of discrete data to content types. This enables us to create rich content models. The Field API allows us to define these distinct field types by creating a new plugin. These plugins specify a FieldType
annotation. In this tutorial, we'll look at these annotations in detail. We'll look at the implementations of field types from Drupal core. Also, we'll see what a new custom field type would look like.
By the end of this tutorial, you should be able to:
- Understand how field type definitions are created and exposed to Drupal
- Identify the various field types provided by Drupal core
- Understand the requirements for providing a specification for a new field type
Once we've explored the various field types provided by Drupal core, the next component of the Field API to explore is field widgets. Field widgets define how the data structure of the field is displayed on an edit form. When content editors interact with your field type they will be doing so via the field widget you provide. In this tutorial, we'll take a look at the field widgets provided by Drupal core, the plugin type required to define our own custom widget and how we can define multiple widget options for a single field type.
By the end of this tutorial, you should be able to:
- Understand where field widgets fit into the overall Field API
- Implement a custom field widget to support a particular field type
Set up a local development environment to practice Drupal theme development. In order to practice theme development, either on your own or following our Hands-On: Theming guide, you'll need a Drupal site up and running on your computer.
By the end of this tutorial, you should be able to:
- Install Drupal on your computer so you can modify files with a code editor of your choice.
- Generate dummy content so that you have different kinds of pages to theme.
It's time to create the bare-bones structure for a new theme on your site. You should try to complete this exercise based on the information you've learned in this chapter. The video included will walk you through the implementation of this exercise if you need some help. In this exercise you will need to:
- Create an info file that describes a custom theme to Drupal with the regions listed below (we're going to name ours "reboot").
- Enable, and view, a bare-bones custom theme.
Regions:
'Header' (header)
'Primary menu' (primary_menu)
'Secondary menu' (secondary_menu)
'Page top' (page_top)
'Page bottom' (page_bottom)
'Highlighted' (highlighted)
'Featured top' (featured_top)
'Breadcrumb' (breadcrumb)
'Content' (content)
'Sidebar first' (sidebar_first)
'Sidebar second' (sidebar_second)
'Footer first' (footer_first)
'Footer second' (footer_second)
Note: At the end of this exercise, you'll find a video walk-through of the solution.
You can accomplish a lot without needing to change any markup by adding CSS and JavaScript files to your theme. In this exercise you'll create 2 asset libraries and add them to your theme. Specifically, we want to pull in the CSS and JavaScript from the popular Bootstrap framework so that we can make use of its layout utility classes later on. We'll also add a custom CSS file that contains global styles for our site, like setting the page background color.
If you want to try and complete this on your own first you'll need to:
- Add the Bootstrap CSS and JavaScript files to your theme.
- Define an asset library using a THEMENAME.libraries.yml file in your theme.
- Tell Drupal to attach your asset library so that the CSS and JavaScript files it represents are included in the page.
Once that's done your site won't look all that different. But if you view the page source, or look closely, you should see that the Bootstrap files are included along with any CSS rules you placed into your custom style sheet.
Note: Since this course if focused on teaching the Drupal aspects of theme development, and not on writing CSS, we use the Bootstrap CSS. If you don't need it for your project though you can skip it, or add the CSS framework that you want to use instead.
You should try to complete the exercise steps on your own and use the video to help guide you if you get stuck.
Note: At the end of this exercise, you'll find a video walk-through of the solution.
Drupal has a few handy settings you can tweak to make developing themes a little more intuitive and a lot more awesome. This includes disabling some of the caching that Drupal does so you don't need to clear the cache as frequently. We'll also turn off CSS and JS aggregation in a settings file (overriding anything set on the Performance configuration form) so you can see your changes to .js and .css files with just a page refresh. Finally, turning on the Twig debug service will give us some additional contextual information about the templates being used when we view the source code of any page on our site. Walk through the exercise steps, and if you get stuck you can watch the video to see how we implemented this.
If you want to try and complete this on your own you'll need to:
- Make changes to your site's settings.php file. Hint: check out the example.settings.local.php file included with core.
- Modify configuration via a services.yml file. Hint: check out the default.services.yml file included with core.
Once this is done, if you view the source of any page on your Drupal site you should see extra HTML comments with helpful information about which template file was used to generate a section of markup.
Example:
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'node' -->
<!-- FILE NAME SUGGESTIONS:
* node--view--frontpage--page-1.html.twig
* node--view--frontpage.html.twig
* node--2--teaser.html.twig
* node--2.html.twig
* node--page--teaser.html.twig
* node--page.html.twig
* node--teaser.html.twig
x node.html.twig
-->
<!-- BEGIN OUTPUT from 'themes/icecream/templates/node.html.twig' -->
Note: At the end of this exercise, you'll find a video walk-through of the solution.
In order to change Drupal's default markup you need to override template files. The page template controls the overall layout of your theme, including the placement of regions. You should complete the exercise just following the written instructions and you can use the video to help if you get stuck.
If you want to try and do this on your own first you'll need to:
- Override the currently used page.html.twig template file.
- Modify the content of the file to include the regions defined in the theme's .info.yml file.
- Wrap the regions in the page template file with HTML markup using CSS classes from Bootstrap to achieve the example layout below.
Note: At the end of this exercise, you'll find a video walk-through of the solution.
The available dynamic tokens or variables vary from template to template. Each "page" is built from and uses many different templates. In this exercise, we'll continue our template overriding practice by overriding the node template. We'll override it and rename it in such a way that it will only affect article nodes on our Drupal site. We'll practice the process of overriding the template, inspecting the available variables, and customizing the markup. Along the way, we'll practice using the Twig filter without
. You should work on the exercise steps below first, and you can refer to the video if you need some help.
If you want to try and accomplish this on your own first you'll need to:
- Override the node.html.twig template file and target only Article nodes.
- Modify the template so that the content of the image field of a node is output wrapped in a
<div>
independent of the rest of the node's content.
Example:
Note: At the end of this exercise, you'll find a video walk-through of the solution.
In this exercise, we'll continue our template overriding practice by overriding the main menu template. We'll override it and rename it with a file name suggestion so that it will only affect the main menu component of our Drupal site. We'll consult the Bootstrap documentation and add the classes from the base nav component into our overridden main menu template file. Along the way, we'll utilize a variety of methods for adding CSS classes to HTML selectors including using attributes.addClass()
and set
. You should work on the exercise steps below first, and you can refer to the video if you need some help.
If you want to try and accomplish this on your own first you'll need to:
- Override the menu.html.twig template file, using a file name suggestion to target only the main menu.
- Add CSS classes from the base nav component in Bootstrap.
Note: At the end of this exercise, you'll find a video walk-through of the solution.
In this exercise, we'll continue our template overriding practice by overriding the image field template. We'll consult the Bootstrap documentation and add a responsive image class that will apply to any images uploaded by a user to the field_image
field. Once again, we'll add this class to the classes
array in the set
Twig tag. You should work on the exercise steps below first, and you can refer to the video if you need some help.
If you want to try and accomplish this on your own first you'll need to:
- Override the image field template file.
- Add values to the
classes
array withset
.
Note: At the end of this exercise, you'll find a video walk-through of the solution.
In this exercise, we'll practice using the t
fiter in a Twig template. As a best practice, all hard-coded text in a template should be translatable. Simple text (containing no dynamic tokens) can be be passed through the t
filter to achieve this objective. Along the way, we'll also use a basic conditional if
statement with Twig. You should work on the exercise steps below first, and you can refer to the video if you need some help.
If you want to try and accomplish this on your own first you'll need to:
- Add a
<div class="label label-warning">
element to the article node template file that contains the string"This node is not published"
. - Use the
t
filter to make the hard-coded text translatable. - Use basic logic statements with Twig to check if the node is published or not.
Note: At the end of this exercise, you'll find a video walk-through of the solution.
Preprocess functions allow you change existing variables, or add new variables, for a template file using PHP code. In this final exercise for the course, you'll define a PHP function that implements a preprocess hook and define a new variable using PHP and make it available for use within a specific template file. Specifically we want to create a new variable named {{ today }}
that contains the current date and gets passed to the page.html.twig template file. You should work on the exercise steps below first, and you can refer to the video if you need some help.
If you want to try and accomplish this on your own first you'll need to:
Learning objectives:
- Create a THEMENAME.theme file.
- Write a proprocess PHP function that adds variables to a page template file.
Note: At the end of this exercise, you'll find a video walk-through of the solution.
Layout Builder is one of many different approaches to handling editorial layouts in Drupal. Now that it's stable, and part of Drupal core, we expect to see it become the dominant approach over time. However, as with most things in Drupal, there are multiple ways to solve the problem of creating component based flexible layouts that can be administered via the user interface.
It's a good idea to understand the different approaches and know what's available.
When it comes to component based design and ability to construct flexible layouts, it is important to understand the benefits and risks of the most popular techniques: Paragraphs, Bricks, entities and view modes, and Layout Builder. Understanding which approach fits the needs of your project best can be critical for its success in the future.
In this tutorial we'll look at some common approaches to administering layouts in a way that gives content editors controls including:
- Drupal core's Layout Builder
- Using core's entity reference fields and view modes
- The contributed Paragraphs module
- The contributed Bricks module
By the end of this tutorial you should have a broad overview of the different popular approaches to creating editor-controlled layouts.
In their simplest form layout plugins in Drupal Layout Builder define the part of the content output that can't be changed. For example a three column layout will consist of three equal columns every time an editor decides to use it as the layout section. The editor can place whatever they want into the three columns. But they can not change the overall layout. This restricts editorial capabilities of using layout plugins since in real life a three column layout may need to consist of a wider middle column and narrower side columns, allow for column headings, or other customizations.
This flexibility is accomplished by creating, and exposing, configuration options for layout plugins in Drupal's Layout Builder. In more advanced cases, the we can take this flexibility further by exposing an interface editors to dynamically define layout plugins.
In this tutorial we'll:
- Learn how to use custom PHP classes in the layout plugin annotation
- Learn what annotations properties can be used for custom layout declaration
- Define the concept of derivatives and outline scenarios for using them
- How to declare static single layouts using YAML format
By the end of this tutorial you'll learn advanced ways of declaring configurable custom layout plugins.
A new favorite page-building and design module in Drupal's core software, Layout Builder makes it possible to create content-type-specific layouts. All nodes of the associated content type will display their content using the defined layout. This allows site builders to display a page's content in two columns, or three, or two columns with a full-width banner image, etc. Then you can place the content type's fields and Drupal blocks into the sections of the defined layout, all via the Drupal UI.
In this tutorial we'll:
- Enable the Drupal Layout Builder and Layout Discover modules
- Create a new two-column flexible layout via the user interface
- Update the Basic page content type so that all nodes use the new two-column layout
By the end of this tutorial you should know how to create a new flexible layout, and apply it to one or more content types.
When building with Layout Builder, the list of blocks available for a site administrator to place in a layout can grow and become overwhelming to navigate. This is especially true when you've got a lot of different modules enabled, as each can add new blocks. As well, complex configurations may require site admins to create more and more custom blocks. Some blocks, like certain Views, or default core blocks like "Who's online", are not meant to be used within the Layout Builder. These blocks can clutter the UI and also impact the performance of Layout Builder UI. The contributed module Block List Override is designed to help solve this problem.
In this tutorial we'll:
- Learn what the Block List Override module does
- Install and configure the module to improve the user experience when creating layouts
By the end of this tutorial you should know how to use the Block List Override module to improve the UX of the Layout Builder interface.