WP Blocks – Gutenberg – not rendering $content

ServerSideRender uses the Block Renderer API endpoint (/wp/v2/block-renderer/<name>) which does not parse inner blocks, hence the $content in your block render callback would naturally be empty.

However, retrieving the inner blocks is pretty easy and as you’ve thought, you can set the blocks (or their content) as an attribute that you would pass to ServerSideRender.

But you don’t need to save the attribute (using setAttributes()), so it will act just as a “dummy” attribute that you would use with ServerSideRender so that the block render callback would receive the inner blocks.

Working Example

  1. So I’m using innerContent as the name for the dummy attribute, but just use any name that you like, and make sure to register the attribute in PHP. E.g.

    register_block_type( 'mydomain/block-wp-block-image-overlay-01', array(
        'render_callback' => 'my_block_render_callback',
        'attributes'      => array(
            // the dummy attribute
            'innerContent' => array(
                'type'    => 'string',
                'default' => '',
            ),
    
            // your other attributes
            'editorSize'   => array(
                'type'    => 'string',
                'default' => 'md',
            ),
            // ...
        ),
        // ...
    ) );
    

    But in JS, you don’t need to actually add the attribute in the attributes property of your block type (that’s registered using registerBlockType()).

  2. Then in your MyServerSideRender, retrieve the content of the inner blocks and include the content in the attributes property of the ServerSideRender element:

    Note: I’m using POST as the httpMethod because that method will allow a bigger attributes object.

    // ... your code here.
    const { compose } = wp.compose;
    // 1. After the above line, add the following:
    
    // These are used to retrieve the inner block content.
    const { getBlock } = select( 'core/block-editor' );
    const { getBlockContent } = wp.blocks;
    
    // 2. Then define MyServerSideRender like so:
    const MyServerSideRender = () => {
        // Retrieve the inner block content.
        const innerContent = getBlockContent( getBlock( clientId ) );
    
        // Then append the innerContent to the attributes object below.
        return (
            <ServerSideRender
                block="mydomain/block-wp-block-image-overlay-01"
                attributes={ { ...attributes, innerContent } }
                httpMethod="POST"
            />
        );
    };
    
  3. And then in the block render callback, you would use the dummy (innerContent) attribute like so:

    function my_block_render_callback( $attributes, $content ) {
        // On the front-end (or non REST API requests), we use $content.
    
        if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
            return '<h3>MyServerSideRender output</h3>' . $attributes['innerContent'];
        }
        return $content;
    
        /* Or you could instead just do:
        return $content ? $content : $attributes['innerContent'];
        */
    }
    

So try those and let me know how it goes? =)

Leave a Comment