How to build a Gutenberg plugin to add functionality to the block editor

Over the years, we have explored Gutenberg from many perspectives. We have dissected the editor’s functionalities, compared them with those of other page builders, built static and dynamic custom blocks, and much more.

With the latest versions of WordPress, new features and tools allow you to create complex layouts more easily by enriching and enhancing the functionality of the block editor without the need to build custom blocks.

Thanks to the introduction of block patterns and developer tools such as the Block Bindings API, there are fewer use cases for custom blocks. You can now create complex block structures, inject metadata values into your content, and automate a good part of your workflow without leaving the editor’s interface. In short, today, WordPress allows you to create complex sites with as few clicks as ever before.

Adding custom controls and tools to the editor may help make the content creation process smoother. For example, you may need to add a panel to the Post sidebar to add functionality or create a custom sidebar to manage multiple meta fields.

Let’s get started!

How to create a block editor plugin without creating a custom block

WordPress provides a convenient command-line tool that allows you to install a local Node.js development environment with all the necessary files and dependencies to create a custom block. Just type npx @wordpress/create-block in the command line tool, wait a few seconds, and you are done.

However, scaffolding a custom block is not necessary when you only need to add a sidebar or a simple settings panel. In this case, you need to create a Gutenberg plugin.

WordPress does not provide a utility to automate the process of creating a plugin for Gutenberg, so you need to do it manually. But do not worry too much. The process is relatively straightforward, and we will drive you through it. These are the steps to follow:

1. Download and install a local development environment

First things first: Although you can develop your Gutenberg plugin in a remote environment, it may be more convenient for you to install a development WordPress website locally. You can use any environment based on PHP and MySQL. Among the many alternatives available out there, we recommend DevKinsta. It’s free, fully featured, easy to use, and 100% compatible with Kinsta hosting.

Once you have your development site set up, you are ready to create a Gutenberg block editor plugin.

2. Download and install Node.js and npm

Download Node.js from nodejs.org and install it on your computer. This will also install npm, the Node package manager.

Once you’ve done this, launch your command-line tool and run node -v and npm -v. You should see the installed versions of Node.js and npm.

Check node and npm versions
Check node and npm versions

3. Create your plugin’s folder

Create a new folder under wp-content/plugins and rename it my-sidebar-plugin or something similar. Just remember that this name should reflect your plugin’s name.

Open the terminal, navigate to the plugin’s folder, and initialize an npm project with the following command:

npm init -y

This will create a basic package.json file.

Create a basic package.json file
Create a basic package.json file

4. Install dependencies

In your command-line tool, type the following command:

npm install @wordpress/plugins @wordpress/scripts --save-dev

A new node_modules folder should have been added to your project.

Now, open your package.json and update the scripts as follows:

{
	"name": "my-sidebar-plugin",
	"version": "1.0.0",
	"main": "index.js",
	"scripts": {
		"build": "wp-scripts build",
		"start": "wp-scripts start"
	},
	"keywords": [],
	"author": "",
	"license": "ISC",
	"description": "",
	"devDependencies": {
		"@wordpress/plugins": "^7.14.0",
		"@wordpress/scripts": "^30.7.0"
	}
}

Now you can check the plugin’s folder:

The plugin's project in Visual Studio Code
The plugin’s project in Visual Studio Code

5. Create the plugin’s files

In your plugin’s directory, create a new .php file and give it the same name as your folder. In our example, it is my-sidebar-plugin.php.

Open the file and paste the following code to register the plugin on the server:

<?php
/**
 * Plugin Name: My Sidebar Plugin
 */

function my_sidebar_plugin_register_script() {
	wp_enqueue_script(
		'my_sidebar_plugin_script',
		plugins_url( 'build/index.js', __FILE__ ),
		array( 'wp-plugins', 'wp-edit-post' ),
		filemtime( plugin_dir_path( __FILE__ ) . 'build/index.js' )
	);
}
add_action( 'enqueue_block_editor_assets', 'my_sidebar_plugin_register_script' );

Next, create a src folder in your plugin’s directory. In there, create a new index.js file with the following code:

import { registerPlugin } from '@wordpress/plugins';
import { PluginSidebar } from '@wordpress/edit-post';

const MyPluginSidebar = () => (
	<PluginSidebar
		name="my-sidebar-plugin"
		title="My Sidebar Plugin"
	>
		<div>
			Hello my friends!
		</div>
	</PluginSidebar>
);

registerPlugin( 'my-sidebar-plugin', {
	render: MyPluginSidebar,
} );

6. Compile the code

All that is missing is the build. Go back to the command line and run the following command:

npm run build

This creates a build folder with the project’s compressed files.

The plugin's project folder in VSC
The plugin’s project folder in VSC

When done, navigate to the Plugins screen in your WordPress dashboard and activate the plugin. Create a new post or page and click the plug icon in the top right corner to display your custom sidebar.

A custom sidebar in the post editor
A custom sidebar in the post editor

7. Develop and build

We have placed the index.js file in the src folder. Using a src folder is a common convention in WordPress plugin and theme development, making your code easier for other developers to understand.

By placing your JS code in the src folder, you can use the npm start or npm run start command to start a development environment that monitors the scripts and automatically recompiles the code when necessary. When you are done with development, the npm build or npm run build command will compile the JavaScript code into the build folder, which will contain the code optimized for production.

Now, let’s put what we learned into practice and modify the plugin we have created in the previous section to add a new panel to the post editor sidebar to manage custom fields.

How to create an additional sidebar to manage post meta fields

Our goal is to create a custom sidebar that contains a panel with a single text field for adding and editing a custom meta field.

Before going into it, we should mention that we could use a custom meta box to achieve the same result. With WordPress 6.7, meta boxes have received an upgrade and are now fully compatible with the block editor, so you may wonder why manage meta fields from a custom sidebar instead of a meta box. The reason is that a sidebar allows you to take advantage of built-in components. This helps you build more friendly interfaces with powerful controls that should also be familiar to users.

That being said, here is the process for creating a custom sidebar that allows you to manage custom fields from within the editor.

my-sidebar-plugin.php

Step 1: Register post meta

First, you need to register the meta field. Add the following code to the main file of the plugin:

function my_sidebar_plugin_register_meta() {
	register_post_meta(
		'post',
		'meta_fields_book_title', 
		array(
			'show_in_rest' => true,
			'type' => 'string',
			'single' => true,
			'sanitize_callback' => 'sanitize_text_field',
			'label' => __( 'Book title', 'my-sidebar-plugin' ),
			'auth_callback' => function() { 
				return current_user_can( 'edit_posts' );
			}
		)
	);
}
add_action( 'init', 'my_sidebar_plugin_register_meta' );

The register_post_meta function accepts three arguments:

  • The post type to register a meta key for. Setting an empty string would register the meta key across all existing post types.
  • The meta key to register. Note that we are not using an underscore at the beginning of the meta key. Prefixing the meta key with an underscore would hide the custom field, so you may want to use it in a meta box. However, hiding the custom field would prevent the meta field from being used via the Block Bindings API in the post content.
  • An array of arguments. Note that you must set show_in_rest to true. This exposes the meta field to the Rest API and allows us to bind the meta field to block attributes. For the other attributes, see the function reference.

Step 2: Register meta box

To ensure backward compatibility for your plugin, you need to register a custom meta box to allow users to manage your custom fields, even if using the classic editor. Add the following code to your plugin’s PHP file:

/**
 * Register meta box
 * 
 * @link https://developer.wordpress.org/reference/functions/add_meta_box/
 * 
 */
function my_sidebar_plugin_register_meta_box(){
	add_meta_box(
		'book_meta_box', // Unique ID
		__( 'Book details' ), // Box title
		'my_sidebar_plugin_meta_box_callback', // Content callback
		array( 'post' ), // Post types
		'advanced', // context
		'default', // priority
		array('__back_compat_meta_box' => true) // hide the meta box in Gutenberg
	 );
}
add_action( 'add_meta_boxes', 'my_sidebar_plugin_register_meta_box' );

Now declare the callback that builds the form:

/**
 * Build meta box form
 * 
 * @link https://developer.wordpress.org/reference/functions/wp_nonce_field/
 * @link https://developer.wordpress.org/reference/functions/get_post_meta/
 * 
 */
function my_sidebar_plugin_meta_box_callback( $post ){
	wp_nonce_field( 'my_sidebar_plugin_save_meta_box_data', 'my_sidebar_plugin_meta_box_nonce' );
	$title = get_post_meta( $post->ID, 'meta_fields_book_title', true );
	?>
	<div class="inside">
		<p><strong><?php echo __( 'Book title', 'my-sidebar-plugin' ); ?></strong></p>
		<p><input type="text" id="meta_fields_book_title" name="meta_fields_book_title" value="<?php echo esc_attr( $title ); ?>" /></p>
	</div>
	<?php
}

Next, write the function to save your meta fields into the database:

/**
 * Save metadata
 * 
 * @link https://developer.wordpress.org/reference/functions/wp_verify_nonce/
 * @link https://developer.wordpress.org/reference/functions/current_user_can/
 * @link https://developer.wordpress.org/reference/functions/sanitize_text_field/
 * @link https://developer.wordpress.org/reference/functions/update_post_meta/
 * 
 */
function my_sidebar_plugin_save_meta_box_data( $post_id ) {
	if ( ! isset( $_POST['my_sidebar_plugin_meta_box_nonce'] ) )
		return;
	if ( ! wp_verify_nonce( $_POST['my_sidebar_plugin_meta_box_nonce'], 'my_sidebar_plugin_save_meta_box_data' ) )
		return;
	if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
		return;
	if ( ! current_user_can( 'edit_post', $post_id ) )
		return;
	if ( ! isset( $_POST['meta_fields_book_title'] ) )
		return;

	$title = sanitize_text_field( $_POST['meta_fields_book_title'] );

	update_post_meta( $post_id, 'meta_fields_book_title', $title );
}
add_action( 'save_post', 'my_sidebar_plugin_save_meta_box_data' );

We won’t dive deeper into this code since it is beyond the scope of this article, but you can find all the information you need by following the links in the function headers.

Last, we need to enqueue our plugin’s index.js file:

function my_sidebar_plugin_register_script() {
	wp_enqueue_script(
		'my_sidebar_plugin_script',
		plugins_url( 'build/index.js', __FILE__ ),
		array( 'wp-plugins', 'wp-edit-post' ),
		filemtime( plugin_dir_path( __FILE__ ) . 'build/index.js' )
	);
}
add_action( 'enqueue_block_editor_assets', 'my_sidebar_plugin_register_script' );

That’s all for the PHP file. Next, we need to write the JS code.

index.js

Your index.js is located in the src folder, which is where you store your JS files during the development phase.

Open your index.js and add the following import declarations:

import { __ } from '@wordpress/i18n';
import { registerPlugin } from '@wordpress/plugins';
import { PluginSidebar } from '@wordpress/editor';
import { PanelBody, PanelRow, TextControl } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { useEntityProp } from '@wordpress/core-data';

You need these resources to build the sidebar with the required controls.

Next, you need to build the sidebar component:

const MyPluginSidebar = () => {
	const postType = useSelect(
		( select ) => select( 'core/editor' ).getCurrentPostType(),
		[]
	);
	const [ meta, setMeta ] = useEntityProp( 'postType', postType, 'meta' );

	const bookTitle = meta ? meta[ 'meta_fields_book_title' ] : '';

	const updateBookTitleMetaValue = ( newValue ) => {
		setMeta( { ...meta, meta_fields_book_title: newValue } );
	};

	if ( postType === 'post' ) {
		return (
			<PluginSidebar
				name="my-sidebar-plugin"
				icon="book"
				title="My plugin sidebar"
			>
				<PanelBody title="Book details" initialOpen={ true }>
					<PanelRow>
						<TextControl 
							value={ bookTitle }
							label={ __( "Book title" ) }
							onChange={ updateBookTitleMetaValue }
							__nextHasNoMarginBottom
						/>
					</PanelRow>
				</PanelBody>
			</PluginSidebar>
		);
	}
};

registerPlugin( 'my-sidebar-plugin', {
	render: MyPluginSidebar,
} );

The registerPlugin function registers the plugin and renders the component named MyPluginSidebar.

The function MyPluginSidebar declares a few constants and returns the JSX code of the component.

  • useSelect is a custom hook for retrieving props from registered selectors. We used it to get the current post type. See also this blog post from the WordPress Developer Blog.
  • useEntityProp returns an array of meta fields and a setter function to set new meta values. See also the online reference.
  • updateBookTitleMetaValue is an event handler that saves the bookTitle meta field value.

We used a few built-in components to build our sidebar:

Now run the npm run build command, activate the plugin, and create a new post. A new book icon should appear in the top sidebar. Clicking on that icon shows your plugin sidebar.

A custom sidebar with a meta field
A custom sidebar with a meta field

What if you don’t need a new sidebar but want to display your custom field in the built-in post sidebar? You just need to replace PluginSidebar with PluginDocumentSettingPanel. This is your new index.js file:

import { __ } from '@wordpress/i18n';
import { registerPlugin } from '@wordpress/plugins';
import { PluginDocumentSettingPanel } from '@wordpress/edit-post';
import { PanelBody, PanelRow, TextControl } from '@wordpress/components';

import { useSelect } from '@wordpress/data';
import { useEntityProp } from '@wordpress/core-data';

const MyPluginSidebar = () => {
	const postType = useSelect(
		( select ) => select( 'core/editor' ).getCurrentPostType(),
		[]
	);
	const [ meta, setMeta ] = useEntityProp( 'postType', postType, 'meta' );

	const bookTitle = meta ? meta[ 'meta_fields_book_title' ] : '';

	const updateBookTitleMetaValue = ( newValue ) => {
		setMeta( { ...meta, meta_fields_book_title: newValue } );
	};

	if ( postType === 'post' ) {
		return (
			<PluginDocumentSettingPanel 
				name="my-sidebar-plugin"
				title="Book details" 
				className="my-sidebar-plugin"
			>
				<PanelRow>
					<TextControl 
						value={ bookTitle }
						label={ __( "Book title" ) }
						onChange={ updateBookTitleMetaValue }
						__nextHasNoMarginBottom
					/>
				</PanelRow>
			</PluginDocumentSettingPanel>
		);
	}
};

registerPlugin( 'my-sidebar-plugin', {
	render: MyPluginSidebar,
} );

The following image shows the result.

A custom settings panel in the Post Sidebar
A custom settings panel in the Post Sidebar

A use case: a block pattern override to automate your workflow

You can now add a value for the custom field, and it will be available through the Block Bindings API for use with block attributes. For example, you can add a Paragraph block to your content and bind the custom field to the paragraph’s content attribute.

Binding meta fields to block attributes
Binding meta fields to block attributes

You are free to change the value of your custom field, and these changes will be automatically applied to the content of your paragraph.

If you are wondering if there’s more that you can do with custom fields and Block Bindings, the answer is yes! Block patterns and Block Bindings API allow you to automate the entire content creation process.

To have a clue, create a pattern with at least a heading or a paragraph. In this example, we create a block pattern with a Columns block, an Image, a Heading, and a couple of Row blocks, including two paragraphs each.

A Columns block with an image, a heading, and two rows
A Columns block with an image, a heading, and two rows

Once you are happy with your layout, select the wrapping elements and create a synced pattern.

Create pattern
Create pattern

Add a name and a category for the block pattern, and make sure to sync it.

Add new pattern
Add new pattern

Next, if you created the pattern in the Post editor, select it and click on Edit original in the block toolbar. You can also navigate to the Patterns section of the Site editor and find the pattern under My Patterns or in the pattern category you have set before.

Open the Code Editor and find the block you want to bind to your custom field. In the block delimiter, add the following code:

<!-- wp:heading {
	"metadata":{
		"bindings":{
			"content":{
				"source":"core/post-meta",
				"args":{
					"key":"meta_fields_book_title"
				}
			}
		}
	}
} -->
The block pattern in the Code editor
The block pattern in the Code editor

Save the pattern and create a new post. Add the pattern to your content and set a value for the custom field. You should see that value automatically applied to your pattern.

A bound Heading in a synced pattern
A bound Heading in a synced pattern

Now, you can play around with this plugin. Thanks to custom fields and the Block Bindings API, you can add more fields and controls to automatically populate your layouts.

Summary

Developing a custom block can be challenging. But do you need to build a block when you can do more with a block pattern?

With the advancements in block patterns and the introduction of powerful developer features, such as the Block Bindings API, creating custom blocks to build sophisticated and functional websites is no longer necessary. A simple plugin and a block pattern can effectively automate a significant portion of your workflow.

This tutorial demonstrated how to add functionality to the WordPress post editor through a plugin. However, what we have covered in this post only scratches the surface of what you can accomplish with the robust features WordPress now offers.

Have you already explored these features and added functionality to the WordPress editor? If so, feel free to share your experiences and insights in the comments section below.

The post How to build a Gutenberg plugin to add functionality to the block editor appeared first on Kinsta®.

版权声明:
作者:dingding
链接:https://www.techfm.club/p/184442.html
来源:TechFM
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>