0

I have a custom post type with a custom Gutenberg template to only display a custom Gutenberg block. This is where the user configures things.

I have another block for all other post types where the user can reference one of the custom post types to display in a post, page, etc.

I'm using render_callback(), and everything works fine, except the rendered output on a post, page, etc, does not update when the user updates the configuration in the custom post type. The preview/front-end of the custom post type updates fine when saved. But anything referencing it seems to be stuck at the time it was referenced and won't display updates unless the user removes the block and re-selects it.

How can I propagate the updates from the custom post type render_callback() output to the regular posts that reference it?

I'm not even sure what to Google search for in this case.

Edit: Was asked for some code.

plugin.php

public function block_init() {
    register_block_type( __DIR__ . '/build', array(
        'render_callback' => array($this, 'render_callback_dynamic')
    ) );
}

public function render_callback_dynamic ($block_attributes, $content) {
    ob_start();
    include 'blocks/template.php';
    $output = ob_get_clean();

    if ( $output === '' ) {
        $output = (string) $content;
    }

    return $output;
}

Edit.js

import { useSelect } from "@wordpress/data";
import { CUSTOM_POST_TYPE } from '../../constants'
import Editor from '../Editor'
import Selector from '../Selector'

const Edit = (props) => {
  const { isCustomPostType } = useSelect((select) => {
    const { getCurrentPostType } = select("core/editor");
    return {
        isCustomPostType: getCurrentPostType() === CUSTOM_POST_TYPE,
      };
  });
  return isCustomPostType ? <Editor {...props} /> : <Selector {...props} />
}

export default Edit

The thinking here is that the Edit component returns either the configuration component or the selector component if on the custom post type or a regular post.

When the configuration changes on the custom post type page, the front-end view of the custom post type does reflect the changes. It is just that the references in a regular post are not updating unless the block is removed and re-added. No caching is being used.

2
  • Do you have some code you can share? The output of render_callback is dynamic, so its output should update unless you are using some kind of caching. Commented Apr 6, 2023 at 2:38
  • Updated with code samples. Commented Apr 6, 2023 at 2:50

1 Answer 1

0

Answer - When the post saves a version of the block, it saves it with the current custom post type blocks attrs as its own attrs. This locks the attrs from the custom post type to the regular post at that time.

A solution is to get the custom block type id and get the block, parse the attrs and use those.

find_block method taken from: Get specific Blocks from Post

    public function find_blocks( array $blocks, string $type = 'custom_post/block' ) : array {
        $matches = [];
    
        foreach( $blocks as $block ) {
            if( $block['blockName'] === $type )
                $matches[] = $block;
    
            if( count( $block['innerBlocks'] ) ) {
                $matches = array_merge(
                    $matches,
                    find_blocks( $block['innerBlocks'], $type )
                );
            }
        }
    
        return $matches;
    }

    public function render_callback_dynamic (array $block_attributes, string $content) : string {
        
        $attributes = (object) $block_attributes;
        $customPostId = (int) property_exists($attributes, 'customPostId') ? $attributes->customPostId: 0;

        if ($customPostId) {
            $post = (object) get_post($customPostId);
            $blocks = (array) $this->find_blocks(parse_blocks($post->post_content));
            $block = (array) array_key_exists(0, $blocks) ? $blocks[0] : array();
            $block_attributes = (array) array_key_exists('attrs', $block) ? $block['attrs'] : $block_attributes;
        }

        ob_start();
        include 'blocks/template.php';
        (string) $output = ob_get_clean();

        if ( $output === '' ) {
            $output = (string) $content;
        }

        return $output;
    }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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