It may surprise you that you can leverage the block editor and save your content in whatever format you like, no HTML comments required.
This article will explain how Gutenberg empowers developers to do that, what we chose to do with the NextGen Form Builder, and other formats you might consider for your own projects.
Why Gutenberg uses HTML Comments to Store Content
The WordPress block editor uses HTML comments to store data about blocks, such as the block type and attributes. This approach has a few advantages:
- It allows for backwards compatibility: By storing the block data in HTML comments, the block editor can work with existing content that was created using the classic editor.
- It makes it easy to parse the blocks: The HTML comments provide a clear delimiter for where one block begins and another ends, which makes it easy to parse the content and identify individual blocks.
- It allows for easy access to block data: By storing data about the blocks in HTML comments, the block editor can easily access and modify the block data without having to rely on JavaScript or other complex methods.
- It’s easy to extract the data using regular expressions: Which is more efficient than using a DOM parser.
- It fails gracefully if a block no longer exists: In contrast to shortcodes, if a dynamic block is uninstalled then the HTML comment placeholder is not rendered on the front end . No more seeing coded markup when you disable a plugin on your site!
Overall, storing block data in HTML comments is a simple and efficient way for the WordPress block editor to work with and manage the content created using the editor.
How the Storage Mechanism Works and Can be Leveraged
It’s important to keep in mind that this is how the block editor works – using HTML comments is not a requirement of working with the Gutenberg codebase. If you dig into Gutenberg’s code you’ll see that the <BlockEditorProvider/>
and <BlockList/>
components work in arrays of block objects that can be interacted with however you like.
Each block has the clientId
and isValid
properties, for use within the editor, in addition to the name
, attributes
, and innerBlocks
properties, which represent the underlying data that is later rendered as post content.
This array of blocks can be serialized and stored for use in the editor for any type of application. This means that while the block editor generates HTML, other applications – like the NextGen Form Builder for GiveWP – can store JSON or any other format according to the needs of the application.
How to Store Your Block Content However You Like
The GiveWP NextGen Donation Form Builder illustrates how the same underlying block data used by Gutenberg can be stored in multiple different formats. Instead of storing annotated HTML for content, GiveWP stores JSON which is then parsed into the Fields API before being consumed by a React application which is the Donation Form.
How the block data is stored is not dictated by Gutenberg, but rather by the application implementing the resulting block editor. As the Gutenberg project grows and gains attention from the broader community there are examples of block editors using Gutenberg in other frameworks and ecosystems. Consider the following implementations:
- Drupal, a popular CMS written in PHP, uses Gutenberg to create landing pages.
- The Laravel community created Laraberg for integrating blocks into custom applications.
- The CF7 Blocks plugin stores block data as shortcodes used by Contact Form 7.
- The Site Builders Guild uses Gutenberg with headless WordPress to create a static blog.
- GiveWP uses Gutenberg to create a NextGen Donation Form Builder focused on User Experience and Developer Experience.
How GiveWP Stores Block Data
This section is more technical in nature, but the short version is that GiveWP stores block data as JSON, instead of HTML comments, for rendering donation forms. This separation of the storage of the data from the resulting HTML enables us to leverage the form data in flexible and dynamic ways, including client side form rendering as well as server side validation using the same data.
The NextGen Donation Form Builder for GiveWP uses TypeScript to enforce the structure of the FormState
and underlying blocks
and settings
properties.
ts
type FormState = {
blocks: Block[];
settings: FormSettings;
};
Each Block
in the FormState
is typed to match the structure as defined by Gutenberg, as previously mentioned.
ts
type Block = {
clientId: string;
name: string;
isValid: boolean;
attributes?: {/*...*/}
innerBlocks?: Block[]
}
The configuration of blocks is derived directly from the <BlockEditorProvider />
and is stored using the React Context API.
jsx
<BlockEditorProvider value={blocks} onChange={dispatchFormBlocks}>
<BlockList />
</BlockEditorProvider>
The block data is passed to the server, parsed into a BlockCollection
from the passed JSON, added to the DonationForm
object, and validated. Because GiveWP uses this block data as a form schema, the Fields API is used to convert the BlocksCollection
into a format that is consumable by the rendered form. The resulting form schema is used to ensure that the block data is valid before being persisted to the database.
php
$form = DonationForm::find($formId);
$form->blocks = BlockCollection::fromJson(
$request->get_param('blocks')
);
$this->validateRequiredFields($form->schema())
$form->save();
Join the NextGen Form Builder Journey
We are building this new experience in public and you can join and follow along.
As a quick teaser, here’s an example of our progress on the “Design Tab”:
If you want to join us on this journey, head to the project page and sign-up to get notified of our progress, get sneak peek previews, participate in polls, and you might even get discount codes and swag items too!
Join the Journey today.