WordPress/gutenberg

Block Bindings API iteration for 6.5

SantosGuillamot opened this issue · 11 comments


This tracking issue is meant to be used to discuss and shape the implementation of the Block Bindings API. Gathering the potential list of tasks and sharing progress on them.

Goal

This API aims to connect block attributes to values, obtained from different sources, that might vary depending on the context. For example, a value like post_author that changes depending on the current post.

This will expand the capabilities of existing blocks without the need to create new ones, which will empower theme developers and site owners. For example, having a heading block with the content of the Post Author without needing a new Post Author block.

Why this API?

Working on connecting block attributes and custom fields triggered many discussions around whether the logic used there could be reused for other projects like Partially Synced patterns. After some proof of concepts and research, it seems that at least the Partially Synced patterns could benefit from the same abstraction. And it could be reused to connect to other sources like site data, external tools, shortcodes, or even other blocks. Additionally, they all share similar concepts, so, the same way the code can be reused, it may make sense to unify part of the UI to ensure everything is coherent.

Hence, this new Block Bindings API.

Projects that will benefit from this API

As mentioned above, there are some ongoing initiatives that I believe could benefit from this API:

For discussing these projects, please refer to their respective issues. There might be more projects that I’m not aware of that could use it, so please share them here, and I can include them in this list.

Additionally, I feel this could be useful for other future projects as well.

How does the API work technically?

Until now, we have been working on this API as part of the Custom Fields project, and there are some proof of concepts already in place.

I like to think about the API as a three steps process:

  1. Create a binding between block attributes and a source.
  2. Get the value from the source defined in the binding.
  3. Update the HTML using the value obtained from the source.

1. Create a binding between block attributes and a source.

This can be done via a “bindings” object that contains the relevant information.

"bindings": {
    "content": {
        "source": "meta_fields",
        "key": "post_author"
    }
}

2. Get the value from the source defined in the binding.

Depending on the source, the value will be obtained from a different place using PHP. For example, in the case of the meta_fields source, it will use the get_post_meta function, while a hypothetical shortcode source could use the do_shortcode function.

Each source will take care of its logic.

Additionally, although there will be core sources like “meta_fields”, developers should have a mechanism to add their custom sources.

Some sources on top of my mind that I believe could be useful:

  • Meta fields: These could include post fields or custom fields.
  • Site data: To show fields like Site Title, site URL, etc.
  • User data: To show fields related to the current user like user name, user email…
  • Pattern: Partially Synced Patterns will likely need a custom source for them.
  • Block: To get the attributes from other blocks, probably using an ID.
  • Shortcode: To show the result of a shortcode.
  • Any external tool using Gutenberg: If other tools, like Drupal, adopt Gutenberg, they could bind blocks to their own sources.

3. Update the HTML using the value obtained from the source.

Once we have the value from the source, we can update the relevant part of the HTML with the block attribute selectors and the HTML API. For example, if it is bound to the paragraph content, it knows it has to replace the inner content, while if it is linked to the image URL, it knows it has to replace the src attribute.

Progressive enhancement

The idea is to embrace progressive enhancement for developing this API and the projects using it. We can start by limiting this functionality to specific core blocks (like paragraph and image), testing how it works, and keep iterating.

We can add support for more blocks progressively. Once we feel confident enough, we can expand it and allow any block from any developer to use this API.

Also, we could explore later the possibility of supporting some of the other sources shared above.

HTML API Dependency

As explained above, this API will rely on the HTML API. Because of that, it’s important to note that the HTML API is still a work in progress. It already offers great APIs to be used here, but there are some limitations right now as well that prevent us from allowing to connect some of the block attributes.

I’ve been taking a look at the current core blocks, and it seems these are the missing functionalities to support ALL of them:

  • Support to mutate HTML to change the inner content of an element. Until we have a set_inner_markup function, we can manually mutate the HTML for our experiments.
  • Support for the PRE HTML element.
  • Support for CSS selectors.
  • Support for H1, H2, H3, H4, H5, H6 HTML elements.
  • Support for lists (OL, UL, LI) HTML elements.
  • Support for CITE HTML element.
  • Support for table (TABLE, THEAD, TBODY, TFOOT, TD, TH) HTML elements.

A group of contributors is working on this, so I’ll try to keep this list updated once support is added. Support for the blocks that depend on this can be added progressively whenever it is ready.

Once the HTML API is mature enough and covers most of the use cases, we can promote this to be used not only by core blocks but also by any block. Until then, we cannot ensure that the HTML API can parse the HTML of external blocks because we are unaware of their structure. For example, if they are using a CITE element and that’s not supported, it wouldn’t work.

Progress

WordPress 6.5

  • Set up the basics to enable other projects like the Custom Fields or Patterns to build on top of it.
  • Create a proper mechanism to add new sources, even if this first version is limited to metadata and pattern.
  • Decide the syntax of the API.
  • Mechanism to change the HTML in the frontend depending on the block attribute source.
    • For attribute source we need to change the HTML attribute depending on the selector.
    • For html source we need to change the HTML inner content. For that, we might need to implement a set_inner_markup private function.
  • Add tests.

Future releases

This is a list of things to consider/questions related to the Block Bindings API that will be updated as we go along:

  • Allow external developers to add support for other sources.
  • Analyze how to support styles as block attributes.
  • Should we provide a way/property to allow users to change the format of the obtained value? (link).
  • Should the block bindings work in the frontend?

In order to approach this and start shaping the API, I believe we can work on the related ongoing projects and polish the API based on their needs.

For this initial phase, I propose focusing on achieving the following:

  • The paragraph, image, and heading block attributes can be connected to custom fields.
  • The paragraph, image, and heading blocks can be edited in partially synced patterns.

This way, we would have a controlled environment while opening up many possibilities, as I consider those blocks will highly benefit from this.

After that, we can work on supporting more blocks progressively and adding support for more complex attributes like styles or other sources if needed.

gziolo commented

The most recent prototype for Partially Synced Patterns #54233 is implementing a modification on the block editor store's level to allow dynamic content inside the setBlockAttributes action. This is also where the Block Bindings API could operate by intercepting the modifications that would previously happen on the block level.

For 6.5, there are plans to include an initial version of:

  • Custom fields and block attributes bindings: link.
  • Partially synced patterns: link.

Both projects will use the Block Bindings API under the hood, so that means we need to ship a working version of it.

Things to consider

These are some of the initial things we need to consider for 6.5, although we will edit this issue once we progress and discover what other things we need to do.

  • Set up the basics to enable other projects like the Custom Fields or Patterns to build on top of it.
  • Create a proper mechanism to add new sources, even if this first version is limited to metadata and pattern.
  • Decide the syntax of the API.
  • Mechanism to change the HTML in the frontend depending on the block attribute source.
    • For attribute source we need to change the HTML attribute depending on the selector.
    • For html source we need to change the HTML inner content. For that, we might need to implement a set_inner_markup private function.
  • Add tests.

I've updated the opening post to reflect this

@SantosGuillamot Could this be used say, to bind a Navigation block link item to it's original Post "source"?

So if I create a link to "My Sample Post", could I use the bindings API to ensure the link stays in sync with changes to "My Sample Post" (both in the Editor and on the front of the site)?

If I understand you correctly the problem is that if you add a link in the navigation block pointing to a post (let's say "My Sample Post"), it uses by default the Label "My Sample Post". But if you modify later the title (let's say "My Updated Post") it still reflects the old one "My Sample Post". Is that right?

Assuming that's the use case, I believe the answer is yes, although I am not fully familiar with how that part of the Navigation works. The way I imagine is that, using the "metadata" source, you could create a binding of the "Label" attribute to the "post_title" of a specific post ID.

By the way, for more information about the implementation of the metadata/custom fields source, which could be used here, you can follow its own tracking issue: link.

I just shared an update on an initial prototype of the block bindings API and some of its sources: link.

👋 Hello team. Whats the update on this feature for WP 6.5? As I understand it the efforts here have been mostly centred on sevring other parts of the 6.5 roadmap such as Custom Fields and Patterns. Is there anything outside of that will land in 6.5 that's important to be aware of?

Here is the original mention of this feature in the roadmap.

Thanks in advance 🙏

Whats the update on this feature for WP 6.5? As I understand it the efforts here have been mostly centred on sevring other parts of the 6.5 roadmap such as Custom Fields and Patterns.

You are right, the focus has been on providing the server side of the bindings, especially needed for the pattern overrides. I believe the same answer than for custom fields apply here: link.

This should certainly ship in 6.5 and we're working on a backport right now: WordPress/wordpress-develop#5888

The remaining features centered around the UI for Block Bindings are a bit uncertain at the moment. We'd like to ship a basic UI and the prototype in #57258 is "working", but it mostly depends on how polished we can make it before 6.5.

I hope we can provide a better scope for 6.5 next week.

Now that we are past the Beta 1 cut off point I'm removing this tracking issue from the 6.5 Project board. From now on the board should only contain individual bugs that we want to still fix before 6.5 gets released.

For simplicity, I'm closing this tracking issue in favor of Epic: Connecting block attributes and custom fields & Block Bindings API.

Both projects are highly related and it seems it is easier to follow if we keep everything under the same discussion. During this last release cycle, we could see that there were many comments related to block bindings in that thread.

The initial rollout in the WordPress 6.5 release introduces a way to define the bindings with block attributes and supporting API on the server that allows registering sources on the server that inject the dynamic data in HTML output for blocks.

Related resources: