WordPress.org

WordPress Developer Blog

Introducing Block Bindings, part 2: Working with custom binding sources

Introducing Block Bindings, part 2: Working with custom binding sources

What if I told you that you could bind custom data from any source to WordPress Core blocks? I’d like to think that it would excite you and get those mental juices flowing.

I know when I first heard that this was possible, I couldn’t wait to try it out. I’ve had so many cool ideas over the years since the introduction of the Block Editor, but no good way to implement them within the system.

WordPress 6.5 will introduce Block Bindings, a new API that will open up a world of possibilities for anyone who needs to dynamically output data without writing custom blocks. In this post, you will learn how to register your own binding source and attach whatever data you want to Core blocks (at least within the limits of what’s possible in 6.5).

In the past few weeks, I’ve built over a dozen features with this new API, and it’s only fair that I share how to do this with you.

This post is a follow-up to Introducing Block Bindings, part 1: Connecting custom fields. I encourage you to read that post first to understand how the Block Bindings API works at a foundational level.

Overview of custom block binding sources

As you learned in the previous post in this series, the Block Bindings API serves as the mechanism for binding attributes to any type of source. WordPress 6.5 will ship two built-in binding sources:

  • core/post-meta: The source for binding custom fields.
  • core/pattern-overrides: The source for handling pattern overrides, another WordPress 6.5 feature. Punted to WordPress 6.6.

For extenders, the core/post-meta source is obviously needed for a lot of projects. But there are many scenarios where you might need to bind data from a different source altogether. Some ideas that come to mind are:

  • Taxonomy term and user data
  • WordPress site data
  • Plugin/theme options
  • Custom database tables
  • A third-party API

There are plans to ship core/site-data, core/user-data, and other binding sources for handling Core data in future releases, but you can certainly start building them on your own in the meantime.

At the block level, custom binding sources work in the exact same way as the core/post-meta source. The big difference is that you have full control over how bindings work under the hood when you register a custom one. And you also have to use the Block Bindings API to register your source.

As discussed in the first post in this series, bindings are limited to the Image, Paragraph, Heading, and Button blocks in WordPress 6.5. Wider support is expected in future versions.

Getting to know the API functions

WordPress 6.5 provides a new register_block_bindings_source() function for registering custom binding sources. It is also used internally to register the custom field and future pattern override sources.

Take a look at the function signature:

register_block_bindings_source(
	string $source_name,
	array $source_properties
);

There are two parameters that you can set:

  • $source_name: A unique name for your custom binding source in the form of namespace/slug.
  • $source_properties: An array of properties to define your binding source:
    • label: An internationalized text string to represent the binding source. Note: this is not currently shown anywhere in the UI.
    • get_value_callback: A PHP callable (function, closure, etc.) that is called when a block’s attribute matches the $source_name parameter.
    • uses_context: (Optional) Extends the block instance with an array of contexts if needed for the callback. For example, if you need the current post ID, you’d set this to [ 'postId' ].

When registering a custom source, you do so on the init hook. So let’s look at an example of what this might look like (we’ll get to a real example in the next section):

add_action( 'init', 'projectslug_register_block_bindings' );

function projectslug_register_block_bindings() {
	register_block_bindings_source( 'projectslug/example-source', array(
		'label'              => __( 'My Custom Bindings', 'projectslug' ),
		'get_value_callback' => 'projectslug_bindings_callback',
		'uses_context'       => [ 'postId', 'postType' ]
	) );
}

That is all the code that is required for registering your binding source with WordPress. 

When WordPress comes across your projectslug/example-source binding source while parsing a block, it will run your callback function. Your function signature should look like this:

projectslug_bindings_callback(
	array $source_args,
	WP_Block $block_instance,
	string $attribute_name
);

It can accept up to three parameters, but you don’t need to define each if you do not need them:

  • $source_args: An array of arguments passed via the metadata.bindings.$attribute.args property from the block.
  • $block_instance: The current instance of the block the binding is connected to as a WP_Block object.
  • $attribute_name: The current attribute set via the metadata.bindings.$attribute property on the block.

To put all of this in the proper context, let’s jump into some real examples.

Decisions: defining the structure of custom bindings

You’ve already learned the basics of how bindings work in Part 1 of this series. Because custom bindings are pretty similar, let’s kick this up another notch and build something slightly more advanced. But don’t worry too much about the complexity—we’re still just covering the basics of what’s possible with the Block Bindings API.

Suppose that you wanted to build a block that showcased a user card. Maybe this is for a company’s team profiles or something along those lines. Depending on the complexity of your user card needs, you might not need a custom block at all. It’s possible you could build it with Core blocks by binding user data to them.

Here’s a screen grab of what we’ll build in the upcoming sections: