- A list of block attributes
editfunction, which describes how the block looks in the editor
savefunction, which describes how the block looks on the front end
Here is a very simple example of a block, borrowed from WordPress’s Gutenberg handbook with a few modifications:
To understand what these three sections are doing, you need to understand how Gutenberg works.
In WordPress today, the post content is a bunch of HTML that you can edit with TinyMCE, the WordPress editor. You type your content into the TinyMCE box, format it, and it saves as HTML. When you display the post content on the front end of the site, the
post_content() function returns that HTML.
Gutenberg needs to return HTML too. But Gutenberg also needs to have a lot more flexibility and complexity in the back end in order to make individual blocks configurable. In the back end, blocks have options for colors and formatting, and some of them have form fields you can fill out. Some parts of blocks have URL inputs or image uploads.
Gutenberg has a clever way of handling the difference between the back-end form and the front-end display: the post content is saved as HTML just like always, but that HTML includes comments that tell Gutenberg how to build the back-end user interface. In other words, that back-end user interface isn’t actually saved anywhere, but it is built on the fly as Gutenberg parses the HTML in the post content.
We’re used to building interfaces such as custom metaboxes where a user fills in a form field and that field is saved in a database with a unique key. We can access the content of the form field by querying the database for that unique key. Gutenberg works completely differently. We might build several input fields into a block, but those inputs are not saved individually. Instead, they are incorporated into the HTML of the post content. When we want to access those inputs in Gutenberg, we don’t query the database for a unique key. Instead, we tell Gutenberg where we saved that data in the HTML, and then we pull it out of the HTML to display and manipulate it in the back end.
Let’s look at the code in detail to see how this works. It actually makes sense to start with the last part of the code, the save function, because this is our end-goal, and everything else depends on it:
This code says that this block needs to return a
div containing an
h2 and another
div with a class of “text.” If we are looking at an existing block (as opposed to a new one), the
h2 will contain the title attribute, and the
div.text will contain the text attribute. In other words, we are telling Gutenberg that our content should look like this:
<div> <h2>The title attribute</h2> <div class="text">The text attribute</div> </div>
This is what will be saved in the post content.
Now, we can back up and look at the first part of our code, where we declare all of our attributes. Now that we know the HTML structure of our block, we can work backwards just like Gutenberg does to build the block in the dashboard.
The first section of the code required to make a block declares everything needed to make the block: the title, icon, category, and attributes. When users add a new block to their content, they will use the title and icon to find the block they want. Gutenberg splits blocks into categories, so you need to declare which category this block belongs to. The attributes are the most important and potentially confusing part of this section.
Each attribute needs three things:
- Type: this is almost always going to be
array, unless you are looking for a number or perhaps a string.
- Source: this is usually going to be
children, because the source of this attribute is a child element of the block
- Selector: this tells Gutenberg which child element of the block to use. For the title, we are telling Gutenberg that the HTML for this block contains an
h2, and that the contents of the
h2are the title attribute. This block also contains a
divwith a class of text, and the contents of that
divare the text attribute.
We have used this code to tell Gutenberg how to parse the HTML that it finds in the content, and split it into the different attributes of our block.
Now that we know what the end product is, and now that we have told Gutenberg what our attributes are, we can build the block input in the WordPress editor:
This is very similar to the save function, for good reason: we want our block to look pretty much the same in both the editor and the front end of the site. This code is telling Gutenberg that we want an editable h2, and if we already have a title attribute, then display that in the h2. We want to have an editable div, and if we already have an attribute of text, then the text should be displayed in the div.
This should help you understand why Gutenberg code is structure the way it is, and the relationship between what happens in the editor and what happens in the post content.