David Yeiser

Create Your Own Dynamic Gutenberg Block for Wordpress, Part 2

A collection of code snippets for building your own custom WordPress Gutenberg blocks.

This is “part 2” of the Create Your Own Dynamic Gutenberg Block for Wordpress tutorial that was published last year. But instead of a narrative step-by-step it’s a collection of useful code snippets you can use to build feature rich custom Gutenberg blocks for WordPress (see the 1/14/20 update at the beginning of part 1 for a little more context for this portion).

The first tutorial covers the infrastructure required to house custom blocks in WordPress, so go there first if you don’t know how to set up your own Gutenberg blocks. Then once that is complete you can add the code snippets below to further develop your custom Gutenberg blocks. The companion GitHub repository tracks the lastest code snippets added here on the master branch. The base code developed in part 1 is maintained in the tutorial/part1 branch.

Important!

Note that the code snippets below should be inserted into the appropriate locations in the file in which they go, never just copy and then replace the full file code, this will break the code. You can always refer to the GitHub repository to see the full context.

Add Image Upload

Steps:

  • Use MediaUpload and MediaUploadCheck from wp.blockEditor.
  • Access Button from wp.components for a UI helper.

Helpful documentation:

index.js

In blocks/book-details/index.js, add the following code:

…

const { MediaUpload, MediaUploadCheck, RichText } = wp.blockEditor
const { Button } = wp.components

…

registerBlockType('davidyeiser-detailer/book-details', {
  …
  // Set up data model for custom block
  attributes: {
    image: {
      type: 'object',
      selector: 'js-book-details-image'
    },
    …
  },
  …

  // The UI for the WordPress editor
  edit: props => {
    // Pull out the props we'll use
    const { attributes, className, setAttributes } = props

    // Pull out specific attributes for clarity below
    const { image } = attributes

    return (
      <div className={className}>
        <MediaUploadCheck>
          <MediaUpload
            className="js-book-details-image wp-admin-book-details-image"
            allowedTypes={['image']}
            multiple={false}
            value={image ? image.id : ''}
            onSelect={image => setAttributes({ image: image })}
            render={({ open }) => (
              image ?
                <div>
                  <p>
                    <img src={image.url} width={image.width / 2} />
                  </p>

                  <p>
                    <Button onClick={() => setAttributes({ image: '' })} className="button is-small">Remove</Button>
                  </p>
                </div> :
                <Button onClick={open} className="button">Upload Image</Button>
            )}
          />
        </MediaUploadCheck>

        …
      </div>
    )
  },

…

index.php

In blocks/book-details/index.php, add the following code:

…

function render_dynamic_block($attributes) {
  // Parse attributes
  $book_details_imageObj = $attributes['image'];
  $book_details_image_url = $book_details_imageObj['sizes']['full']['url'];
  $book_details_image_alt_text = $book_details_imageObj['alt'];
  $book_details_image_width = $book_details_imageObj['sizes']['full']['width'] / 2;

  …

  /* BEGIN HTML OUTPUT */
?>
  <div class="block-book-details">
    <?php if ($book_details_image_url) : ?>
      <img class="book-details-image" src="<?php echo $book_details_image_url; ?>" alt="<?php echo $book_details_image_alt_text; ?>" width="<?php echo $book_details_image_width; ?>" />
    <?php endif; ?>

    …
  </div>
…