WordPress Gutenberg Quick Start (with useful links)

April 2, 2019
I decided early on that I would wait getting on the Gutenberg bandwagon until it actually was going to be released – which it was, last year, with WordPress version 5.0.0.So first off, what is Gutenberg? It’s basically the new wysiwyg editor for WordPress, built with react components, and offering extensions via something called “blocks”.I tried reading through the official documentation (or handbook as they call it), but it’s hopelessly long, with a lot of superfluous information that’s not needed, nor wanted, for somebody who just wants to understand the implementation.So here’s a condensed version of what you need to do if you want to build your own custom block.

Register the block server side

First you’ll have to register your block in wordpress/php. This is pretty straightforward, there’s the function register_block_type which you’ll need to run during the enqueue_block_assets action-hook.All you have to do is send in the name of the block. But in the optional arguments, you can also send in what attributes the block supports, and, and this is important, a server side render function for the block (this means you won’t have to create the block markup in JS).
<?php

function registerMyBlock() {
    $myAttributes = [
        'title' => [
            'type' => 'string',
            'default' => 'The team',
        ],
        'isActive' => [
            'type' => 'bool',
            'default' => true
        ]
    ];

    register_block_type(
        'my-domain/my-block',
        [
            'render_callback' => 'myBlockRender', // This here allows dynamic server side rendering of the block
            'attributes' => $myAttributes
        ]
    );
}

/**
 * Render myBlock block
 * 
 * @param $attrs array The attributes/props of the block
 * @param $content string The content of the block
 * @return string The rendered block
 */
function myBlockRender($attrs, $content) {
    ob_start();
    ?>
        <div>
            <h1><?php echo esc_html($attrs['title']); ?></h1>
            <div>
                <?php echo $content; ?>
            </div>
        </div>
    <?php

    $blockHtml = ob_get_contents();
    ob_end_clean();

    // Wrap with wp:html so autop etc. doesn't mess up the markup
    return do_blocks('' . $blockHtml . '');

}

add_action('enqueue_block_assets', 'registerMyBlock');

?>
So this will make WordPress aware of your block, but it’s not usable yet. You’ll need to actually implement the block on the client side as well.

Register the block client side

I’m opting for the ES6 route when implementing my gutenberg blocks, there are legacy ways as well, but in this age and day…The method for registering a block exists globally in the JS namespace, and it’s called registerBlockType.The important thing to note is that the name needs to be the exact same string as the one you used when registering on the server side (.i.e. in our case my-domain/my-block).There’s a bunch of metadata that you can optionally register, and then there’s the two main methods, edit and save. To simplify it, edit is what’s rendered in the admin panel, save is what’s used to render out in the post.As I noted earlier, you can avoid having to handle the output markup with js by adding a method to the render_callback when registering the block on the server side, you’ll also need to return null from the save method on the client side.If you don’t, it’s worth mentioning that anything outputted by the save method will end up in the $content argument on the server side render method (this is useful for things like repeating blicks with inner-blocks).
const { registerBlockType } = wp.blocks;
const { RichText } = wp.editor;

import Inspector from './Inspector';

/**
 * Register block
 */
export default registerBlockType(
    'my-domain/my-block',
    {
        title: 'My Block Title',
        description: 'This block is used for displaying things',
        category: 'common',
        icon: 'universal-access-alt',    
        attributes: {
            title: {
                type: 'string'
            },
            isActive: {
                type: 'bool',
                default: true
            }
        },
        edit: props => {
            const { attributes: { title, content }, setAttributes } = props;

            return [
                <Inspector {...{ setAttributes, ...props }} />,
                (
                    <div>
                        <RichText
                            tagName="h2"
                            placeholder={'Your title'}
                            value={ title }
                            formattingControls={[]}
                            onChange={ ( title ) => setAttributes( { title } ) }
                            keepPlaceholderOnFocus={true}
                        />
                    </div>
                )
            ];
        },
        save: props => {
            return null; // The server will take care of dynamic rendering
        },
    },
);
For those of you who’ve worked with react will notice the setAttributes method, it’s for all intents and purposes the same as the setState method in react, it’ll update the attributes and then trigger a re-render of the component (or rather parts of the component that uses said attribute).As you might’ve noticed, I’ve also imported something called the Inspector, that’s basically the sidebar for the gutenberg block, which will hold additional settings controls for the block.The inspector is just a simple react module, but the basic gists is that you want to wrap your controls in something called panels, which are basically accordion dropdown sections.
const { Component } = wp.element;
const { InspectorControls } = wp.editor;
const { PanelBody, ToggleControl } = wp.components;

export default class Inspector extends Component {
    constructor() {
        super(...arguments);
    }

    render() {
        const {
            attributes: {
                isActive
            },
            setAttributes
        } = this.props;

        return (
            <InspectorControls>
                <PanelBody
                    title={"Options"}
                    initialOpen={true}
                >
                    <ToggleControl
                        label={'Is active?'}
                        checked={isActive}
                        onChange={isActive => setAttributes({ isActive })}
                    />
                </PanelBody>
            </InspectorControls>
        );
    }
}
And that’s all there is to it. You’ve now created your first block.

Additional information

I had a hard time finding a list of available built-in and native gutenberg components that you can use when building your own block. So after digging around the source code, here’s a couple of nice-to-have links that’ll come handy when developing your own blocks.List of built-in controls that you can useList of the built-in blocks that exists, useful if you want to find out how they work.One of the more interesting built-in elements is the inner-blocks, which allows wrapping / repeating other blocks, here’s the implementation / documentation.

Tags