17

I'm playing with Gutenberg ahead of its inclusion in core, and I'd like to know how to extend the existing gallery block to change its display. For example, instead of a grid of thumbnails I'd like to show a slideshow of images. Is it possible? If so, how? Any help would be appreciated.

3
  • 1
    There's a chapter on Extensibility in the Gutenberg Handbook, that might be the first step to see if those filters from the Modifying Blocks part can be utilized for this case..
    – birgire
    Commented Mar 19, 2018 at 15:59
  • It seems that this chapter has been added recently. I didn't see it before. In any case, as it's marked as experimental, this feature is prone to change. I'll wait until it's stable. Thanks!
    – leemon
    Commented Mar 19, 2018 at 22:18
  • The following doc is more up to date: github.com/WordPress/gutenberg/blob/master/docs/…
    – leemon
    Commented Mar 20, 2018 at 11:55

2 Answers 2

20

Ok, I've been playing with this for a little bit and have managed to change the output of the Gallery block, with the following caveats:

  • The preview does not match the output. I think this is possible but appears to be a bit more involved.
  • Certain classes and markup are required in the output for the block to be able to parse the content and keep it editable. These classes have front-end styles that will need to be dealt with. I'm not sure at this point if there is a way to filter how the block does this. If it were possible it might not even be a good idea if it means Gallery blocks are broken when a theme or plugin is deactivated. A totally new block would probably be the way to go for situations where this would be required.
  • I'm not really sure how image sizes work at this stage.
  • The method of JavaScript hooks used might not be relevant in the final release. Gutenberg uses @wordpress/hooks while discussion about what hooks system to use in Core is ongoing.
  • Since the output of Blocks is saved as HTML, not a shortcode or meta, it won't be possible to modify the output of existing Galleries without editing them.

The first thing we need to do is register a script. This is done with wp_enqueue_scripts(), but on the enqueue_block_editor_assets hook.

The script should have the wp-blocks script as a dependency. It is almost certainly already loaded in the editor, but making it a dependency presumably ensures it is loaded before our script.

function wpse_298225_enqueue_block_assets() {
    wp_enqueue_script(
        'wpse-298225-gallery-block',
        get_theme_file_uri( 'block.js' ),
        ['wp-blocks']
    );
}
add_action( 'enqueue_block_editor_assets', 'wpse_298225_enqueue_block_assets' );

The HTML for a block's output is handled by the save() method of the block. You can see the Gallery block's in this file.

At this stage (March 2018) Gutenberg supports a filter on the save method of blocks, blocks.getSaveElement. We can add a hook to this in JavaScript like this:

wp.hooks.addFilter(
    'blocks.getSaveElement',
    'wpse-298225',
    wpse298225GallerySaveElement
)

The first argument is the hook name, the 2nd argument is - I think - a namespace, and the last argument is the callback function.

Since we are replacing the save() method of the block, we need to return an new element. However, this is not a normal HTML element we need to return. We need to return a React element.

When you look at the original block’s save() method what you see is JSX. React, which Gutenberg uses under-the-hood, supports it for rendering elements. See this article for more on that.

JSX normally requires a build step, but since I'm not introducing a build step for this example, we need a way to create an element without JSX. React provides this with createElement(). WordPress provides a wrapper for this and other react functionality in the form of wp.element. So to use createElement() we use wp.element.createElement().

In the callback function for blocks.getSaveElement we get:

  • element The original Element created by the block.
  • blockType An object representing the block being used.
  • attributes The properties of the block instance. In our example this includes the images in gallery and settings like the number of columns.

So our callback function needs to:

  • Return the original element for non-block galleries.
  • Take the attributes, particularly the images, and create a new React element out of them representing the gallery.

Here is a complete example that simply outputs a ul with a class, my-gallery, and lis for each image with the class my-gallery-item and and img in each one with the src set to the image URL.

function wpse298225GallerySaveElement( element, blockType, attributes ) {
    if ( blockType.name !== 'core/gallery' ) {
        return element;
    }

    var newElement = wp.element.createElement(
        'ul',
        {
            'className': 'wp-block-gallery my-gallery',
        },
        attributes.images.map(
            function( image ) {
                return wp.element.createElement(
                    'li',
                    {
                        'className': 'blocks-gallery-item my-gallery-item',
                    },
                    wp.element.createElement(
                        'img',
                        {
                            'src': image.url,
                        }
                    )
                )
            }
        )
    )

    return newElement
}

Some things to take note of:

  • The original gallery block finds images by looking for ul.wp-block-gallery .blocks-gallery-item, so this markup and those classes are required for editing the block to be possible. This markup is also used for the default styling.
  • attributes.images.map is looping over each image and returning an array of child elements as the content for the main element. Inside these elements there is another child element for the image itself.
1
  • All linked files return 404.
    – TCB13
    Commented Jun 16, 2020 at 11:29
2

Here to provide an updated answer. I found this post extremely helpful in answering the question of how to extend the Gallery Block.

In short, its advisable to just create a new block rather than extending an existing. From the post in my link above:

if you modify the HTML of a block [by extending], it won't be recognized as the original block. Rather than trying to manipulate a core block it seems like unregistering the core block and registering a new replacement block in its place would be a safer approach - that way you're ensuring users of the site use your particular customized gallery, which will validate because it defines its own HTML structure.

The link above also references The Create-Guten_Block plugin which is a command-line tool that will generate everything you need to get you started with Block creation. The tool is very easy to use, and easy setup.

With these resources, I was able to figure out how to develop a custom gallery block in a short time

2
  • Do you have any more tips on creating a gallery block? It seems to me that there is a significant amount of work on the editor side to support all the necessary CRUD functions. The core WP solution handles everything from uploading image to sorting them, adding new ones, deleting existing ones, etc. The way I'm seeing this is that it's a lot of work to recreate the same functionality as comes out-of-the-box just to customize the frontend.
    – phip
    Commented Feb 5, 2020 at 2:06
  • @phip its been about 6 months since I was deep in Gutenberg blocks, and I know lots has changed about it. I agree with what you're saying, if I understand you correctly. It did seem overwhelming to builld custom interfaces to manage crud operations. Advanced Custom Fields Pro version allows you to create custom data schemas for blocks. for more info, https://www.advancedcustomfields.com/resources/blocks/. Though I enjoyed learning to use React to build blocks, using ACF was a huge time saver. Commented Feb 7, 2020 at 21:29

Not the answer you're looking for? Browse other questions tagged or ask your own question.