- how to create a custom page Builder element
- how to register plugins in Webiny applications
Out of the box, Webiny’s Page Builder app provides a plethora of ready-made page elements we can use to create both simple and complex pages for our website. Furthermore, on top of the default set, users can also create their custom page elements, which is what this article demonstrates.
In this short article, we create a relatively simple page element that allows users to show a list of different SpaceX rocket and dragon spacecrafts. Here’s what the final result will look like:
The custom page element will be available from the Media page elements category:
Also, upon dropping the element onto a page, users will have the ability to adjust the following three settings:
- type of spacecrafts to be displayed (rockets or dragons)
- number of spacecrafts to be displayed
- pagination offset (number of spacecrafts we want to skip when retrieving the data)
Note that the spacecrafts data will be retrieved from a non-official public SpaceX GraphQL HTTP API, located at https://spacex-production.up.railway.app/. Meaning, changing these settings will dictate the variables that will be included in GraphQL queries issued by the page element. More on this in the following sections.
To create a custom page element, we first need to create a renderer React component which, as the name itself suggests, renders it. As we’ll be able to see, this is easily achieved via the
createRenderer factory function.
Via a couple of plugins, the next step is registering the renderer React component within our project’s Admin and Website apps.
In case you missed it, the Admin and Website apps are located in the
apps/website folders of an existing Webiny project.
On the Admin app side, we first register the
PbEditorPageElementPlugin plugin, which enables us to introduce our custom page element into the Page Builder’s page editor and enables users to drop the new element onto a page.
After that, optionally, we register the
PbEditorPageElementAdvancedSettingsPlugin plugin, which lets us define all the related settings that are available to users upon dropping the page element onto a page. Since the page element we’re building does contain settings that the user can adjust, we will need this plugin as well.
When it comes to the Website app, here we register the
PbRenderElementPlugin plugin. With it, we ensure our renderer React component is utilized upon serving a published page to an actual website visitor. Note we’ll also need this plugin on the Admin app side because previewing pages is possible there too, outside the page editor.
There are multiple approaches when it comes to where to place our custom page element code. In this tutorial, we will be placing all the code in the
apps/theme folder. More specifically, we’ll create a new
apps/theme/pageElements folder, and inside it, the new
folder can be further used as a folder for all of your custom page elements.
Ultimately, in the
apps/theme/pageElements/spaceX folder, we’ll end up with the following three files:
SpaceX.tsx- contains the renderer React component
admin.tsx- contains the Admin app plugins
website.ts- contains the Website app plugin
If needed, both commands can be run at the same time, via two separate terminal sessions.
As previously mentioned, in order to create a custom page element, we start off by creating a new renderer React component. We create the
apps/theme/pageElements/spaceX/SpaceX.tsx file with the following code:
Note that, for simplicity’s sake, all the code is placed in a single file. Of course, it is possible to organize it across multiple files, if preferred.
Furthermore, in order to be able to issue remote GraphQL queries, we introduce the
graphql-request package. The package can be installed via the following command, run from your project root:
With this code in place, we’re ready for the next step, which is registering the renderer React component within our Admin and Website apps. We’ll start with the Website app, as the plugin that we’ll create here will also be needed within the Admin app.
As previously mentioned, ensuring our custom renderer React component is actually used upon rendering a published page is done via the
PbRenderElementPlugin plugin. For this, we’ll create a new
apps/theme/pageElements/spaceX/website.ts file with the following code:
With this plugin in place, we need to register it within the Website app. This can be achieved via the
With the plugin registered, we’re ready to move on to the next step, and that is the Admin app.
For simplicity’s sake, we’ll again place all the code in a single file, this time in
Before we register these plugins, note that, in order to construct the settings form, we’re using the
@webiny/validation packages. Since the
@webiny/ui is not installed within the
apps/theme package by default, we need to install it. This can be done via the following command, run from your project root:
When it comes to plugin registration, in total, there are three plugins we need to register within the Admin app. The two shown above, plus the previously created
PbRenderElementPlugin plugin. The
PbRenderElementPlugin is required because, as mentioned, pages can also be previewed within the Admin app, outside the page editor.
We register the two plugins via the
PbRenderElementPlugin plugin can be registered via the
With all the plugins registered, we’re now ready to give this a try locally in our browser.
With the above steps correctly completed, we should be able to see our custom page element in Page Builder’s page editor and be able to drop it onto a page. The page element should also be correctly rendered when previewing the page, and also on the public website, once the page has been published.
Creating custom page elements is certainly an interesting option when users need more than what the default set of page elements provides.
On the code level, this could be creating completely custom (renderer) React components, including needed external NPM libraries, or even issuing remote HTTP requests to external HTTP APIs in order to retrieve data from standalone external systems.
On the other hand, custom page elements also add additional flexibility by allowing content creators to tweak elements’ settings and, ultimately, help them achieve more with just a single page element.
In certain cases, you might need to control the style of the element wrapper. This is that orange box that shows around your custom element when you select it in the editor. Because your custom element is nested inside this element wrapper, it can affect the way your custom element is displayed, and you might need to make some adjustments to the styles of the wrapper itself.
To do that, you can provide the
baseStyles property inside the options of the
createRenderer function. This property accepts an object with CSS properties, which will be applied to the element wrapper.
In another case, you might need to set certain style properties of your custom element to specific values. For example, by default, if you drop in an element into the editor its height is set to
100%. But what if you have a case where you want your specific element to say have a default height of
250px, you can take the following approach. Inside
<PbEditorPageElementPlugin> you can define the
data.settings property and set the default value for the height property, or for any other property that you want to set.
In this particular case, since the Page Builder controls the height property per device breakpoint you need to import both
DisplayMode to correctly set the