Like the blog? Get the book »

Gutenberg Block Recipes

Gutenberg Block Recipes

I’ve been working on updating my collection of WordPress plugins for the imminent Gutenberg update. So far it has not required much time to learn, and the API is straightforward. It will however take significantly longer to integrate Gutenberg support into 20+ plugins. To help keep things organized, I will be posting tips and snippets here at DigWP.com. Blocks are the foundation of all things Gutenberg, so this first post is all about block recipes. Some of these code snippets are far less useful than others, hopefully they will be useful to others.

Note! To help save time, I refer to Gutenberg as G7G or g7g throughout this article (e.g., in code snippets).

Basic block with style

Displays a static block with some padding and basic styles. Includes i18n support.

const { __ } = window.wp.i18n;
var el = wp.element.createElement,
	registerBlockType = wp.blocks.registerBlockType,
    blockStyle = { backgroundColor: 'red', color: 'white', padding: '20px' };

registerBlockType('g7g-blocks/block-01', {
	title: __('Pancakes'),
	icon: 'universal-access-alt',
	category: 'common',
	edit: function() {
		return el('p', { style: blockStyle }, __('For Breakfast'));
	},
	save: function() {
		return el('p', { style: blockStyle }, __('For Dinner'));
	},
});

Block to add inline style

This dynamic block accepts CSS styles and displays them inline on the frontend. Includes i18n support.

const { __ } = window.wp.i18n;

var el = wp.element.createElement,
	registerBlockType = wp.blocks.registerBlockType,
	Editable          = wp.blocks.Editable,
	createBlock       = wp.blocks.createBlock;

registerBlockType('g7g-blocks/block-02', {
	title: __('Style'),
	icon: 'art',
	category: 'formatting',
	keywords: ['css', 'inline', 'style'],
	attributes: {
		content: {
			source: 'text',
			selector: '.wp-block-g7g-blocks-block-02',
		},
	},
	supports: {
		html: !1,
		customClassName: !1,
	},
	edit: function(props) {
		var content = props.attributes.content;
		function onChangeContent(style) {
			props.setAttributes({
				content: style.target.value
			})
		}
		return el('textarea', {
			className: props.className,
			onChange: onChangeContent,
			value: content,
			placeholder: __('Add style (do not include <style> tags)')
		})
	},
	save: function(props) {
		var content = props.attributes.content;
		return el('style', {
			dangerouslySetInnerHTML: {
				__html: content
			}
		})
	}
});

Along with that, I used the following CSS:

.wp-block-g7g-blocks-block-02 { width: 100%; height: 200px; }

Block to display notes

This block displays a note on the frontend. Includes i18n support.

const { __ } = window.wp.i18n;

var el = wp.element.createElement,
	registerBlockType = wp.blocks.registerBlockType;

registerBlockType('g7g-blocks/block-03', {
	title: __('Note Block'),
	icon: 'admin-post',
	category: 'common',
	attributes: {
		type: {
			type: 'string',
			default: 'important',
		},
		message: {
			type: 'string',
			source: 'html',
		},
	},
	edit: function(props) {
		var className = props.className;
		var type = props.attributes.type;
		var message = props.attributes.message;
		function updateMessage(event) {
			props.setAttributes({ message: event.target.value });
		}
		return el('p', {
			className: className +' note-'+ type 
		}, 
		el('textarea', { 
			value: message, 
			onChange: updateMessage 
		}));
	},
	save: function(props) {
		var type = props.attributes.type;
		var message = props.attributes.message;
		return el('p', { 
			className: 'note-' + type 
		}, message);
	},
});

Also applied these styles:

.wp-block-g7g-blocks-block-03 textarea { width: 100%; height: 200px; }
.wp-block-g7g-blocks-block-03.note-important { color: red; }

Block to display latest post

This block displays the latest post. Modified to include i18n support and other tweaks.

const { __ } = window.wp.i18n;

var el = wp.element.createElement,
	registerBlockType = wp.blocks.registerBlockType,
	withAPIData = wp.components.withAPIData;

registerBlockType('g7g-blocks/block-04', {
	title:    __('Latest Post'),
	icon:     'megaphone',
	category: 'widgets',
	
	edit: withAPIData(function() {
		return {
			posts: '/wp/v2/posts?per_page=1'
		};
	})(function(props) {
		if (!props.posts.data) {
			return __('Loading...');
		}
		if (props.posts.data.length === 0) {
			return __('No posts.');
		}
		var className = props.className;
		var post = props.posts.data[0];
		
		return el('a', { 
			className: className, 
			href: post.link 
		}, post.title.rendered);
	}),
	
	save: function() {
		// render via PHP
		return null;
	},
});

Notice near the end of the block code, where it says, “render via PHP”? That’s where this next snippet comes into play. Add this code to via plugin or theme functions.php:

function g7g_render_block_latest_post($attribites) {
	
	$recent_posts = wp_get_recent_posts(array('numberposts' => 1, 'post_status' => 'publish'));
	
	if (count($recent_posts) === 0) return __('No posts');
	
	$post = $recent_posts[0];
	$post_id = $post['ID'];
	
	return sprintf(
		'<a class="wp-block-g7g-latest-post" href="%1$s">%2$s</a>',
		esc_url(get_permalink($post_id)),
		esc_html(get_the_title($post_id))
	);
	
}

function g7g_load_blocks() {
	
	register_block_type('g7g-blocks/block-04', array('render_callback' => 'g7g_render_block_latest_post'));
	
}
add_action('init', 'g7g_load_blocks');

Note that last function, g7g_load_blocks() is a workaround for the error: “PHP Fatal error: Uncaught Error: Call to undefined function register_block_type”. So at some point whenever that is fixed, we can just call register_block_type() directly without the workaround.

Block that uses rich-text field

This block displays a Rich Text Editor, so the user can include HTML content along with any text. I.e., formatted text. Includes i18n support.

const { __ } = window.wp.i18n;

var el = wp.element.createElement,
	registerBlockType = wp.blocks.registerBlockType,
	RichText = wp.blocks.RichText;
	
registerBlockType('g7g-blocks/block-05', {
	title: __('Message'),
	icon: 'universal-access-alt',
	category: 'common',
	attributes: {
		content: {
			type: 'array',
			source: 'children',
			selector: 'p',
		}
	},
	edit: function(props) {
		var content = props.attributes.content;
		function onChangeContent(newContent) {
			props.setAttributes({ content: newContent });
		}
		return el(RichText, {
				tagName: 'p',
				className: props.className,
				onChange: onChangeContent,
				value: content,
				isSelected: props.isSelected,
			}
		);
	},
	save: function(props) {
		return el('p', { 
			className: props.className 
			}, props.attributes.content
		);
	},
});

Also added the following bit of CSS:

.wp-block-g7g-blocks-block-05 textarea { width: 100%; height: 200px; }

Blocks, Blocks, Blocks

More Gutenberg blocks on the way.. in fact, in about a month or two, the Web literally will be drowning in Gutenberg block tutorials. I absolutely 1000% guarantee it ;)

2 responses

  1. This is really great, Please posts snippets like these. It helps people me to understand and delve right into Gutenberg

  2. Definitely appreciate posts like this while I continue wrapping my head around Gutenberg. Thanks! Keep it up!

Comments are closed for this post. Contact us with any critical information.
© 2009–2024 Digging Into WordPress Powered by WordPress Monzilla Media shapeSpace