Building Dynamic Blocks for the Gutenberg Editor in WordPress

In order to build dynamic blocks in the new Gutenberg WordPress editor we turn to our old friend, PHP and a render_callback function.

Now that we’ve gone over how the edit and save functions work with the new Gutenberg editor, we know that it’s easy to save custom markup for our block. Throw in the RichText component and we can create easily editable blocks.

But what if we want to build a block that dynamically displays data from the database? That’s where dynamic blocks come into play. And for that we’ll turn back to our trusty old friend, PHP.

When are Dynamic Blocks with PHP Useful

Using PHP to create dynamic blocks is needed if you’re working with a block that needs to update data without saving a post.

Let’s say for example we want to pull in recent posts. If we’re just using the save function with JavaScript out saved markup will be the most recent posts from the last time the current post was updated. If we add a post in the future it won’t know to update the markup.

With server-side rendering through PHP we can tell the block to reach out to the database to pull in the most recent posts when the block is rendered to the user.

The Rules of Dynamic Blocks

There are a few considerations to keep in mind when using dynamic blocks.

You should still make the edit function a representation of how the block will be displayed on the frontend. This is made easier by using the REST API or the <ServerSideRender> component. More on both in a bit.

The save function can either return null which forces the content to be rendered server-side every time. This is perfectly acceptable for more blocks.

Alternatively you can make the save function a cached version of the block that can be displayed if the plugin containing the block is deactivated. Essentially you’re saving some form of fallback markup for the block to use in the case the server-side rendering function goes away.

Creating the edit Screen with the REST API

You’ll still be calling registerBlockType in your JavaScript. With the only caveat being that if you’re using attributes, they’ll be defined in PHP instead of JavaScript. You will still be able to set those attributes with setAttribute though. More on that in a minute.

In the case of a latest posts block or other blocks accessing information form the database we can take advantage of the REST API using a handy withAPIData that we can access from thewp.components library.

Update: The withAPIData function will be deprecated in a future version of Gutenberg. I’m working on an update for creating this, but in the meantime you can try out the <ServerSideRender> component explained later in the article.

To make that a little simpler what we essentially have is withAPIData( // REST API call )( // function to run with returned API data )

So in the first portion we’re simply running the withAPIData function to get the 3 most recent results from our posts endpoint.

Note: That’s not valid code. Don’t copy only that.

Then the second part is essentially our callback function that we want to run with the data to output our preferred markup. We’re returning different markup in a few situations here:

  1. While the API is loading posts
  2. If the API returns no results
  3. When the API returns results
In each of these return statements we can make use of any attributes we may have used in the past. And even use custom components like <RichText> to output user entered data. But we’ll need to register the custom attributes through PHP.

First here’s an example of fully function edit function for outputting 3 recent posts.

Rendering the Block Server Side with PHP

In order for a block to have a server component for display we need to make use of the render_callbak on the register_block_type function.

Not to be confused with the JavaScript function registerBlockType, the PHP function register_block_type is hooked into the init action.

register_block_type takes two arguments, the namespace/block-name and an object for several arguments including attributes and render_callback which we’ll be using.

Let’s take a look at this in action.

In our JavaScript edit function above we added a <RichText> component for setting a content attribute as an <h2> for our latest posts list.

Since we’ll need to access that attribute with our PHP function we need to define the attribute in our register_block_type call. We’re doing on lines 3-7 above. By defining the attributes in PHP we don’t want to define them in JavaScript as well.

Defining attributes in PHP allows for the $attributes to be passed to our render_callback function. Which we’re setting with 'render_callback' => 'prefix_dynamic_block_posts',.

Next we need to define the prefix_dynamic_block_posts function which will make our dynamic call to the database and return our posts.

This is a short example that shows our block outputting “This displays on the frontend”. Not super useful at this point, but this is just to illustrate how the callback returns content.

Let’s take a look at a full example that gets our 3 most recent posts, uses our content attribute, and outputs it all in some nice markup.

Rather than break that down I’ve added comments to the code to explain what each portion of the code is doing.

Bonus: Rendering the edit Screen Server Side 🤯

One of the newer features of Gutenberg (since 2.8) is the addition of the <ServerSideRender> component that simplified creating the editor representation for dynamic blocks.

This component allows the editor to render the block based on the PHP render_callback function.

You’ll need to make sure to include the ServerSideRender component from the wp.components library to use it.

That will look like this at the top of your block.js file.

const { ServerSideRender } = wp.components;

Implementing the <ServerSideRender> component in our edit function then looks like this:

Wrapping Up

In order to create blocks with dynamic data make use of the PHP register_block_type function with a render_callback. You can then render your blocks in the edit screen using the <ServerSideRender> component or make use of the Rest API using withAPIData.

With these tools you can start building some seriously awesome blocks.