1

I am building a custom website with custom blocks and have recently decided to translate all my blocks into dynamic blocks. The blocks that do not use InnerBlocks are fine, but I cannot figure out how to render a dynamic InnerBlock inside another dynamic block.

I used the advice from another post to mix the save() method and return InnerBlocks.Content, after which you render the InnerBlocks content with $content inside the render_callback function. This is what it looks like:

// counter/save.js
import { __ } from "@wordpress/i18n";
import { InnerBlocks } from "@wordpress/block-editor";

const Save = (props) => {
  return <><InnerBlocks.Content /></>;
};
export default Save;
// counter.php
function counter_render_callback($attr, $content)
{
  ob_start(); // Turn on output buffering

?>

  <?php if (!empty($content)) : ?>
  <section class="bg-blue-900 thin text-white">
    <div class="container flex flex-wrap justify-evenly md:justify-around text-center -mb-10 md:mb-0">
      <?php echo do_blocks($content); ?>
    </div>
  </section>
  <?php endif; ?>

<?php
  /* END HTML OUTPUT */

  $output = ob_get_contents(); // collect output
  ob_end_clean(); // Turn off ouput buffer

  return $output; // Print output
};

Now I set up my InnerBlock to also act as a dynamic block, but it only renders that which I set up in it's save.js file. This is what the InnerBlock looks like:

// counter-list/save.js
import { __ } from "@wordpress/i18n";
import { useBlockProps } from "@wordpress/block-editor";

const Save = (props) => {
  const { attributes } = props;

  const mandatoryFields = () => {
    return attributes.amount && attributes.label;
  };

  const blockProps = useBlockProps.save();
  return (
    <div {...blockProps}>
      {mandatoryFields() && (
        <div class="w-1/2 sm:w-1/3 md:w-auto mb-10 md:mb-0">
          <div class="font-display text-h1 font-medium leading-none">
            {attributes.amount}
          </div>
          <div class="w-10 h-px bg-white my-4 inline-block opacity-60"></div>
          <div>{attributes.label}</div>
        </div>
      )}
    </div>
  );
};
export default Save;
// counter-list.php
function counter_list_render_callback($attr, $content)
{
  // Easier access to all attributes
  $amount = !empty($attr['amount']) ? $attr['amount'] : "";
  $label = !empty($attr['label']) ? $attr['label'] : "";

  // Do not output anything if any of the mandatory fields are empty
  if (empty($amount) || empty($label)) {
    return;
  }

  ob_start(); // Turn on output buffering

?>

<div class="w-1/2 sm:w-1/3 md:w-auto mb-10 md:mb-0">
  <div class="font-display text-h1 font-medium leading-none"><?php echo $amount; ?></div>
  <div class="w-10 h-px bg-white my-4 inline-block opacity-60"><?php echo $label; ?></div>
</div>

<?php
  /* END HTML OUTPUT */

  $output = ob_get_contents(); // collect output
  ob_end_clean(); // Turn off ouput buffer

  return $output; // Print output
};

How do I make my counter.php file use the render_callback function from counter-list.php?

1 Answer 1

1

Instead of removing the question, I'll answer the question myself for those that seek to find the same answer. My InnerBlock was called counter-list.php, which causes a problem as I have a counter_list_render_callback function. When looping through all my blocks, it tries to find counter-list_render_callback which is an invalid function name and therefore fails to render.

Make sure to name your files so that you can reuse their names for the render_callback functions.

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.