I’m building a dynamic block in a custom plugin that shows code in my blog posts. I’m struggling with this bug where the output of the render_callback function gets echoed out to the WP dashboard when editing that post.
Here’s what the HTML (just the top) of the post edit page looks like:
test (frontend)test (frontend)test (frontend)<!DOCTYPE html>
<html class="wp-toolbar"
lang="en-US">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /
This is what my init.php file looks like (my render_code_block function at the end of the file):
<?php
/** * Blocks Initializer * * Enqueue CSS/JS of all the blocks. *
* @since 1.0.0 * @package CGB */
// Exit if accessed directly. if (!defined('ABSPATH')) { exit; }
/** * Enqueue Gutenberg block assets for both frontend + backend. *
* Assets enqueued: * 1. blocks.style.build.css - Frontend + Backend. * 2. blocks.build.js - Backend. * 3. blocks.editor.build.css - Backend. * * @uses {wp-blocks} for block type registration & related functions. * @uses {wp-element} for WP Element abstraction — structure of blocks. * @uses {wp-i18n} to internationalize the block's text. * @uses {wp-editor} for WP editor styles. * @since
1.0.0 */ function fe24_post_blocks_cgb_block_assets() { // phpcs:ignore // Register block styles for both frontend + backend. wp_register_style(
'fe24_post_blocks-cgb-style-css', // Handle.
plugins_url('dist/blocks.style.build.css', dirname(__FILE__)), // Block style CSS.
is_admin() ? array('wp-editor') : null, // Dependency to include the CSS after it.
null // filemtime( plugin_dir_path( __DIR__ ) . 'dist/blocks.style.build.css' ) // Version: File modification time. );
// Register block editor script for backend. wp_register_script(
'fe24_post_blocks-cgb-block-js', // Handle.
plugins_url('/dist/blocks.build.js', dirname(__FILE__)), // Block.build.js: We register the block here. Built with Webpack.
array('wp-blocks', 'wp-i18n', 'wp-element', 'wp-editor'), // Dependencies, defined above.
null, // filemtime( plugin_dir_path( __DIR__ ) . 'dist/blocks.build.js' ), // Version: filemtime — Gets file modification time.
true // Enqueue the script in the footer. );
// Register block editor styles for backend. wp_register_style(
'fe24_post_blocks-cgb-block-editor-css', // Handle.
plugins_url('dist/blocks.editor.build.css', dirname(__FILE__)), // Block editor CSS.
array('wp-edit-blocks'), // Dependency to include the CSS after it.
null // filemtime( plugin_dir_path( __DIR__ ) . 'dist/blocks.editor.build.css' ) // Version: File modification time. );
// WP Localized globals. Use dynamic PHP stuff in JavaScript via `cgbGlobal` object. wp_localize_script(
'fe24_post_blocks-cgb-block-js',
'cgbGlobal', // Array containing dynamic data for a JS Global.
[
'pluginDirPath' => plugin_dir_path(__DIR__),
'pluginDirUrl' => plugin_dir_url(__DIR__),
// Add more data here that you want to access from `cgbGlobal` object.
] );
/** * Register Gutenberg block on server-side. * * Register the block on server-side to ensure that the block * scripts and styles for both frontend and backend are * enqueued when the editor loads. * * @link https://wordpress.org/gutenberg/handbook/blocks/writing-your-first-block-type#enqueuing-block-scripts
* @since 1.16.0 */ register_block_type(
'fe24/fe24-code-block',
array(
// Enqueue blocks.style.build.css on both frontend & backend.
'style' => 'fe24_post_blocks-cgb-style-css',
// Enqueue blocks.build.js in the editor only.
'editor_script' => 'fe24_post_blocks-cgb-block-js',
// Enqueue blocks.editor.build.css in the editor only.
'editor_style' => 'fe24_post_blocks-cgb-block-editor-css',
'render_callback' => 'render_code_block'
) ); }
function render_code_block($attributes) {
// $content = $attributes['code'];
// echo "<pre><code>$content</pre></code>";
echo 'test (frontend)'; }
// Hook: Block assets.
add_action('init', 'fe24_post_blocks_cgb_block_assets');
And finally my block.js:
/**
* BLOCK: fe24-post-blocks
*
* Registering a basic block with Gutenberg.
* Simple block, renders and saves the same content without any interactivity.
*/
// Import CSS.
import "./editor.scss";
import "./style.scss";
const { __ } = wp.i18n; // Import __() from wp.i18n
const { registerBlockType } = wp.blocks; // Import registerBlockType() from wp.blocks
const { RichText, InspectorControls } = wp.blockEditor;
const {
ToggleControl,
PanelBody,
PanelRow,
CheckboxControl,
SelectControl,
ColorPicker,
} = wp.components;
registerBlockType("fe24/fe24-code-block", {
// Block name. Block names must be string that contains a namespace prefix. Example: my-plugin/my-custom-block.
title: __("fe24 code block"), // Block title.
icon: "editor-code", // Block icon from Dashicons → https://developer.wordpress.org/resource/dashicons/.
category: "common", // Block category — Group blocks together based on common traits E.g. common, formatting, layout widgets, embed.
keywords: [__("fe24 code block"), __("code"), __("fe24")],
attributes: {
// languages: {
// type: "array",
// },
selectedLanguage: {
type: "string",
},
code: {
type: "string",
},
},
edit: (props) => {
const languages = ["javascript", "css", "html", "php"];
return (
<div>
<InspectorControls>
<PanelBody title="Fe24 Code Block Settings" initialOpen={true}>
<PanelRow>
<SelectControl
label="Language"
value={props.attributes.selectedLanguage}
options={languages.map((language) => {
return { label: language, value: language };
})}
onChange={(newval) => {
props.setAttributes({ selectedLanguage: newval })
console.log(newval);
}
}
/>
</PanelRow>
</PanelBody>
</InspectorControls>
<RichText
tagName="code"
placeholder="Insert your code"
value={props.attributes.code}
onChange={(newval) => {
console.log(newval);
props.setAttributes({ code: newval });
}}
/>
</div>
);
},
save: () => {
return null;
},
});
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
Excerpt from “Creating dynamic blocks” in the block editor handbook:
The server-side rendering is a function taking the block and the block
inner content as arguments, and returning the markup (quite
similar to shortcodes)
So despite the “render” as in render_callback, a block render callback should not actually echo anything (and neither call any functions that echo something) and instead, return the output — which will later be automatically echoed by WordPress. Therefore in your render_code_block() function, you need to replace the echo with return, i.e. use return 'test (frontend)';..
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0