How to make an editable WordPress Gutenberg block

The new WordPress editor is coming and we have to deal with it if we want to ship new cool things on the new WordPress editor interface.

Before writing your first editable Gutenberg block, you should read how to write a simple block.

WordPress provides a quite good Gutenberg Handbook for developers if you need to read more.

With an editable block, you’ll be able to make a block that will let the user edit content. In this tutorial, we’ll learn how to create a link block:

Let’s do this.


The easiest way to write a block is just use plain JS, however the best looking and most understandable code will only be achieved with JSX ECMAScript markup. In order to do that, you have to go through some simple tooling for compilation:

  • NPM/Node
  • Babel

Recipe ingredients

  • The PHP plugin file that will queue and register the JS and the CSS.
  • Babel configuration files: .babelrc, package.json and webpack.config.js.
  • NPM to install and compile the block.
  • The block itself in JS.

PHP part

First you need to register and queue everything:

  • The block JS file.
  • The style for the block.
  • The style for the website page side of the block.
  • Queue the block itself and it’s styles.

You can do that like this:

  • I’m queuing the block script.
  • Registering both styles.
  • Using register_block_type() to link the block and it’s styles and script by their slugs.

The first param of register_block_type() is the name of the block. It has to have a namespace, like this:


Change the line 10 to ‘block-simple’ so our name is going to be


The same name will be used on the block.js.

Setting up the block environment

The block will be written using the new fancy JSX little thing. For me, that’s the only way to go. For that, you’ll have to install the ‘compiler’. That’s not really complicated.

Create a folder inside your plugin for the block and put these 3 files:




Those files are configured to compile your block.js into a You’ll code block.js and upload in your plugin, that’s the file that your plugin has to queue.

Then, just install it running NPM on the block folder.

npm install

Later on, you’ll compile your block.

That’s what you need to start writing your block

Everything you done until here works for any type of block. Now we’re going to write the editable block.

In Gutenberg, not all blocks are editable. A simple non-editable block will only add a fixed HTML to render while the editable block will let you code an interface where the user can edit data.

In this example, we’ll make a block for a simple link where the user will be able to edit the name and URL of the link.

Please, if you never wrote a block, it’d be better if you write a simple block first.

The block part

For this, you just have to use some required components and call registerBlockType() with the block name and an object with some parameters, the attributes and two required methods: edit() and save().

  • attributes: an object with the data that will let you bind the DOM
  • edit(): renders the editor markup of the block
  • save(): renders the site markup of the block

You’ll also need to use a component that let the user edit data. The best way to do that is with the component RichText.

RichText Component

This component provides you with an RichText tag that creates some sort of input field. With this editable tag, you’ll add some crucial attributes such as:

  • onChange callback: a callback for whatever changes in the field value
  • value: the binded value from the DOM
  • placeholder: an input placeholder text
  • className: styling class


Going back to the attributes, it’s a simple object that creates a structure to let the component know how to extract data from the DOM.

There are many ways to make this structure, but in this example, we’re using those properties:

  • selector: the DOM selector, like a tag or a class.
  • source: the source of the data, in this example we’ll use ‘children’, so it’s the child node of the tag. We also can use ‘attribute’ for the attribute of a DOM tag.
  • attribute: DOM attribute, like ‘href’ or ‘src’

You can read more on the handbook

Each attribute will bind one single data. In our case we need 2 attributes: link_url and link_text, because those are the two things that the user will edit. It’s an editable block, remember?

To extract data for the link_url, I need to use the attribute href of the tag a, so here’s how I need to set up this attribute:

  • selector: ‘a’
  • source: ‘attribute’
  • attribute: ‘href’

To extract data for the link_text, I need to use the children text of the tag a, so here’s how I need to set up this attribute:

  • selector: ‘a’
  • source: ‘children’

Let’s see the complete code:

edit function

As you can see, we need to edit link_url and link_text, so we have two RichText tags to handle that. Both are bind through the attributes and their changes are listened through the onChange event that calls the functions to update the attributes. That’s the whole idea.

This will be rendered on the WP edit page.

save function

The markup for the website rendering.


That’s the easiest part. The plugin has queued two styles: editor.css and site.css, for the front-end site.

The editor.css will always be included, both in the editor and in the site. The site.css will only be included in the front-end site.

The block will add a class name using the block name prefixed with ‘wp-block’. It’s gonna be like this:


You just need to use this as a class name for your styles.

In the block.js, the edit() method has a className param for that. The save() method doesn’t need that.

Creating the compiled block

Yeah, your block.js won’t work. You need to compile it with the babel tooling that you have installed.

Since block.js is inside the block folder with those 3 special files that you installed with NPM, you just need to run:

npm run dev

It’ll listen to whatever changes to block.js and create and update That’s the file you’ll upload. That’s your built block.

Just upload your styles and and everything will be all right.

The complete plugin code

Go take a look.

Read more