Skip to content

Instantly share code, notes, and snippets.

@mrpsiho
Last active March 17, 2022 10:34
Show Gist options
  • Save mrpsiho/62333214c767711150ce259fd3e2ced0 to your computer and use it in GitHub Desktop.
Save mrpsiho/62333214c767711150ce259fd3e2ced0 to your computer and use it in GitHub Desktop.
Example of Gutenberg block with server side rendering.
(function(blocks, data, compose, element, blockEditor, components, serverSideRender) {
const el = element.createElement;
const registerBlockType = blocks.registerBlockType;
const { InspectorControls } = blockEditor;
const { Fragment } = element;
const { PanelBody, PanelRow, SelectControl } = components;
const useBlockProps = blockEditor.useBlockProps;
const { withSelect } = data;
registerBlockType('prefix/block_name', {
title: 'Block name',
icon: 'calendar-alt',
category: 'widgets',
keywords: ['tag1', 'tag2'],
attributes: {
pid: {
type: 'number'
}
},
edit: function(props) {
const onChangePostId = (id) => {
props.setAttributes({ pid: parseInt(id) });
};
const { pid } = props.attributes;
const PostsDropdownControl = compose.compose(
withSelect(function(select) {
// I get data from posts and pages and combine it
// it is just an example and it is specific to my block
const posts = select('core').getEntityRecords('postType', 'post');
const pages = select('core').getEntityRecords('postType', 'page');
let items = [];
if (posts) {
items = posts;
}
if (pages) {
items = [...items, ...pages];
}
return {
posts: items
}
}))(function(props) {
let options = [];
if (props.posts) {
options.push({ value: 0, label: 'None' });
props.posts
.forEach((post) => {
const title = post.meta.some_meta1 && post.meta.some_meta1 !== ''
? post.meta.some_meta1
: post.title.rendered;
options.push({ value: post.id, label: title });
});
} else {
options.push({ value: 0, label: 'Loading...' })
}
return el(SelectControl,
{
label: 'Select a post',
options: options,
onChange: onChangePostId,
value: pid,
}
);
}
);
const MyServerSideRender = (props) => (
el(serverSideRender,
{
block: 'prefix/block_name',
attributes: {
pid: props.attributes.pid
}
}
)
);
return (
el(Fragment, {},
el(InspectorControls, {},
el(PanelBody, { title: 'MyBlock settings', initialOpen: true },
el(PanelRow, {},
el(PostsDropdownControl, { pid: pid })
)
),
),
el('div', useBlockProps(),
el(MyServerSideRender, props)
)
)
);
},
save() {
return null;
}
});
})(
window.wp.blocks,
window.wp.data,
window.wp.compose,
window.wp.element,
window.wp.blockEditor,
window.wp.components,
window.wp.serverSideRender
);
// this is a method of my plugin's class, not a simple function!
// basically this methods returns HTML just like a shortcode function would do this
public function dynamic_render_callback($attributes, $content) {
global $post;
if ( !$post && empty($attributes['pid']) ) {
return '';
}
$post_id = empty($attributes['pid']) ? $post->ID : $attributes['pid'];
ob_start();
// this method output HTML
$this->template_product_options($post_id);
$form = ob_get_clean();
return $form;
}
register_block_type('prefix/block_name', array(
'api_version' => 2,
'ssr' => true,
'attributes' => [
'pid' => [
'type' => 'number',
'default' => 0
]
],
'render_callback' => function($block_attributes, $content) {
if ( !is_admin() ) {
$this->load_scripts_frontend(true); // this is how I add styles and scripts dynamically
}
// my plugin's class method
return $this->dynamic_render_callback($block_attributes, $content);
}
));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment