How to Build a Custom Dynamic Gutenberg Block Step-by-Step

Alex Cuadra
NicaSource

--

Gutenberg has been surrounded by controversy since the early stages of planning. Even though Gutenberg was included in WordPress’ core in v5.0 “Bebo”, some members of the WordPress community strongly thought Gutenberg wasn’t ready to be implemented even before its release in late 2018. With the latest updates of v6.0 “Arturo”, Gutenberg has evolved and become a handy tool that is easy to use; this has also resulted in an increase in the number of users working with it.

Nowadays, with Gutenberg’s rising popularity, for any WordPress developer, skills like knowing React and how to develop Custom Blocks are essential. So, in this article, I’ll guide you in a step-by-step process on how to build a custom dynamic Gutenberg block.

Gutenberg Blocks

A Gutenberg block consists of multiple reusable components built with React and Redux. Its purpose is to allow users to edit their content like a page builder. We can use blocks for the content and create widgets and sections on our websites like the header and footer.

Non-technical users have a better experience adding content to their sites with a block editor like Gutenberg than with an editor like WordPress’s classic editor since the block editor allows them to have a closer view of what the user is creating in the front-end.

Why Should we Develop a Custom Block?

Gutenberg comes with a lot of good default blocks. However, sometimes we’ll need to create some custom ones to cover our specific needs. For example, when a block is supposed to offer us the possibility to upload a photo or apply a particular style. When creating a custom block, we aim to extend the default editor capabilities.

Should we Create our Block as a Plugin or Within a Theme?

We can register our block in the functions file within our theme. However, if we uninstall the theme, we will lose the rendered content. Thus, ideally, we should use a plugin to create our blocks. Nowadays, creating a custom block can be done without effort by installing this npm package, which will add all the essential files we require to build the plugin.

Dynamic Custom Block Project

What are we going to build?

This article will build a block that returns the weather in a city. Specifically, I will migrate a short-code plugin to a block. For it, we will need to call a weather API like Weather API. We will also need to create a dynamic block instead of a static block because the data coming from Weather API may eventually change.

The current short-code takes a city’s name as an attribute:

And it renders the city’s name, temperature, and current weather:

So, we’ll create a block that receives a city’s name and renders the weather info in the front end.

What do we need?

To get started, we’ll install some tools, including NodeJS, NPM, and the @wordpress/scripts package. We’ll also need a local WordPress installation using one of these tools: local, xampp, or @wordpress/env.

Scaffolding our custom dynamic block

In a terminal, go to the plugins’ folder in your WP installation and run npx @wordpress/create-block [block name].

In my case, I will name my plugin ‘weatherblock.’

Running the npx command will create a new folder with our plugin’s files, including the src directory and the PHP file, where you will find your plugin’s header.

Plugin’s PHP file

In my case, the file is the weatherblock.php. The header is where WordPress registers a plugin. Note that the file will be automatically generated within our root folder.

src Folder

Within the src folder, we’ll see our JavaScript block files which are the main files we will be working on.

Block.json is the file where most of the block’s properties are set. Further in this article, we will revisit the file to add some additional properties.

Activating the New Block

To start building our new dynamic Gutenberg block, we first need to activate our plugin. To activate it, go to the plugins page in your dashboard and click on activate:

In block.json, we will add the block attributes needed to pass the data through the components. For our block, we need to add the “cityName” attribute, where we’ll store the city’s name that sets the weather info we need to get.

As you can see in the screenshot above, you can also change the icon and the category of your block, so it’s easier to find it in the editor:

The next step is to register our block. In weatherblock.php, you will notice that we have the following code block:

The above code was generated by the ‘create-block’ command.

Let me elaborate a bit on the function ‘create_block_weatherblock_block_init’: This function will hook the registration with the initial load of WordPress. Within it, we have the register_block_type that accepts the path where we are building our static JavaScript files as a parameter.

Converting from static to dynamic block

We need to add our render callback function to register_block_type. This function should be where we can render our dynamic data to the front-end.

Since we are building a dynamic block, we don’t need the Save() object in the registerBlockType hook. The Save() object is only required when we want to set the markup that will be saved in the database. So, to accomplish it, we need to select the index.js file of the same object as null, which will prevent the default behavior.

Creating the block with reusable components

Now, we’ll work on the edit.js file. In this file, we will build the block that the user should see within the editor.

In the screenshot above, you can find the dependencies we need to create our block. We may notice that useBlockProps React hook will be imported to the edit.js file. The previous will allow us to pass properties between components and use them in the block’s wrapper element. If the element wrapper is intended to have any extra custom HTML attributes, they need to be passed as arguments to the hook.

Before making changes to our components, we need to run `npm run start` to build and watch them, so our development environment updates accordingly. Then, we can start to work on the edit function:

Since we are building a simple block with an input that receives the city’s name, we will use the TextControl component, which is included in the WordPress component package. Additionally, we must deconstruct the block’s attributes where we have our cityName property. Then, we will use setAtrributes to save the new city’s name in the block.

Now, to see our block working, let’s add a new page to our site and select the block.

If, at this point, you need assistance debugging your block, check the resources tab in the web dev tools.

Saving the Content

Now that we have our Gutenberg block ready in the editor. Let’s work on the logic and the front-end rendering. For this, we have to go back into the main plugin file (in my case, weatherblock.php) and write a function to render the block content. You must name the block as you have named it in the register block hook because it has the render callback method.

The function below will receive three parameters: $attributes, $content, $block. For our plugin, the most important is $attributes, which allows us to get the properties from block.json. The other two, $content, and $block could be used to fetch any content from the editor.

Calling the Weather API

According to the API documentation, we can get weather data specifying the city’s name. To get this, we can use the following endpoint:

https://api.openweathermap.org/data/2.5/weather?q={city name}&appid={API key}

Within the render_weather_widget function, we will create a variable that will store the cityName property from $attributes.

As you can see in the screenshot above, we’ll store the API key in a variable $apiKey, then will save the URL with the API in a variable $fullUrl. And finally, we’ll use wp_remote_get to get the data object.

Then, we are going to store the decoded JSON in a variable that will be used to get the three other variables: $city (which is the city’s name), $temp (temperature), and $weather (main weather).

Finally, we’ll use ob_start() and ob_get_clean() to send the content to the buffer and print it on the front-end.

Adding Styles

The last step is to apply the styles for both the editor and the front-end. To get to this, we have two files:

  • editor.scss: This can be used to apply styles to the editor components, but in our example, we don’t need to use it.
  • style.scss: This will apply styles to the front-end.

Finally, add the block again in the editor, introduce a city’s name, and click on “update.”

Now go to the website page and reload it; you should be able to see something like this:

End-to-end Tests

Now that our Gutengber blocked is complete, we can perform end-to-end tests. First, we have to add some dependencies. We need to install ‘@wordpress/e2e-test-utils’. Then, we’ll use ‘@wordpress/env’, which is a local WordPress environment for building and testing plugins and themes. ‘@wordpress/env’ is simple to install and requires no configuration. Once both are installed, let’s add them to the scripts in package.json.

Before we start working with the tests, be sure that docker is running on your computer! Then, we will need to run “env:start” and finally, we can create our test file. For it, we need to create a file named “weatherblock.spec.js” within the test folder, where the e2e script will search for the spec extension.

The Jest API and the Puppeteer API will be helpful tools for writing the tests. You should look at their documentation for a more in-depth understanding. In this tutorial, we’ll only implement a basic test in the project that will (1) create a new post, (2) insert the block, and (3) check if the block was inserted correctly.

As you can note, we are using methods from e2e-test-utils:

  • In line 1, with the insertBlock function, we provide the block’s name
  • In line 10, we use “expect” to confirm that the block exists in the editor
  • Then, we can select it using the data-type attribute.
  • And finally, just run the “test:e2e” script, and this will run the tests.

This testing method may change in the future as the community is working on migrating the testing architecture to Playwright. In the meantime, we can still use jest and puppeteer.

Wrapping up

We have now created a simple dynamic Gutenberg block that calls an external API. Although we use @wordpress/create-block, this is an optional step as we can use other tools to help us scaffold our project, like create-guten-block.

Additionally, we can modify our project to build a group of blocks instead of a single one. Community templates are available for different approaches. As demonstrated, we can easily create a custom block with dynamic content reusing core components which can help us to develop more complex Gutenberg blocks. We might also want to extend Gutenberg components for more customization.

Gutenberg has come to enhance the user experience on the editor side. The main advantage of migrating short codes to blocks is that the user will avoid errors or typos and be able to check the content rendered on the front-end. Moreover, we can make changes to existing page sections using blocks thanks to the Full Site Editing that uses Gutenberg as page builder. So, blocks are the present and the future of WordPress, and developing them is an essential skill that WordPress devs should have.

References:

Here are some materials you can use to further dive into this learning experience:

--

--