External data
When you build a custom visual builder you usually want to connect it to the data that is specific to your software. Easyblocks allows for a full control over external data:
Connect any external data source. You can define your own widget displayed in the editor to pick data entry of any type (for example a product data from e-commerce platform). You define how the data is fetched and from where.
All the data is fully dynamic. Easyblocks doesn’t store any copies of data inside of its no-code entries. All the data is fetched in your code and provided via
externalData
prop toEasyblocksEditor
orEasyblocks
components (for editing and rendering respectively).Compound data types. Custom data sources can provide compound objects consisting of multiple "basic" data types like text, image or video. Those basic types can be later connected to text fields, images etc. For example you can create a
product
data source (a product data from e-commerce platform) and then connectproduct.title
to a text box orproduct.mainImage
to the image component.Document-level parameters. Your documents can be rendered with different data thanks to the root parameters feature. Imagine you're building an e-commerce platform. Your users want to build a product page template and reuse this template for all the product pages. You can do it by adding a
product
as a root parameter of your document's root component. While editing, users will be able to pick any product data just for preview. When the content is rendered, the product data must be passed dynamically depending on the product page that is being rendered. You can render hundreds of different products pages based on a single template, similar to Shopify Theme Editor. Root parameters allow for building advanced template systems.
Connecting external data sources
Let's imagine we have the following list of products:
Let's define a new No-Code Component Product
to display data of single product:
As you can see, we've used a new type called product
. Right now, Easyblocks doesn't know anything about our custom type and will throw an error that it can't find it. To define a custom type you have to add its definition to types property.
Right now, definition of our new product
type consists only of empty widgets
array, but we will get back to it soon. If we try to add our Product
component to the canvas, the error about missing type is gone, but the sidebar won't display our new field because it doesn't know how to do it. Each type can have one or more widgets to tell the editor how to render input/picker for that particular type. Built-in types have their own widgets that aren't overridable right now.
Let's define a new custom widget for our product
type. Widget's definition is split into two parts:
defining widget within the definition of type
supplying React component for rendering within the editor
After these changes, our ProductPickerWidget
is rendered instead of the error message. The problem is that it doesn't do anything. Let's first examine what our component receives in the props object:
id
(string | null
) - a unique identifier of the currently selected resource, in our case it would be product id. Thisid
is always stored in a No-Code Entry and will be later used for fetching the data. Ifid
equalsnull
it means that no resource is picked.onChange ((newId: string | null) => void)
- this callback should be called by widget code to notify Easyblocks that selected resourceid
changed.
Let's implement a simple widget component using select
element:
Out widget component simply renders all products as available options and an additional option for empty value. Selecting Product
component on the canvas gives us now the access to our custom widget picker from the sidebar.
The only things stored in No-Code Entry are unique id
and widgetId
:
As you can see we don't store a full product object in a No-Code Entry. The full data will be provided dynamically.
The missing piece right now is displaying the selected product. Let's implement React component for our Product
component now:
If we try to render Product
component with empty product
field we will see the following message instead of our component:
This happens because by default each custom type field is required, which means that Easyblocks doesn't render the component until some value is selected (this can be changed with optional
property).
However, even if you select a value for product
field, the component still won't render. It happens because Easyblocks doesn't yet know how to fetch the actual data. To resolve this issue we need to define a custom fetcher. Fetcher is a function that receives external references stored within No-Code Entry and resolves them to their external data. To define a fetcher for editor you need to specify onExternalDataChange
prop.
That callback is invoked each time you update value for your custom type field. The changedExternalData
parameter has the following structure:
Each property represents a field of your defined custom type that was recently updated and its value represents the external reference to some external data. To correctly resolveproduct
type references we need to do the following:
from
externals
select only types ofproduct
map each external reference to its related external data value
return resolved external data in the valid format
Built-in picker
To build a simple usable widget component, Easyblocks comes with SimplePicker
component that can be imported from @easyblocks/design-system
package. It comes with built-in support for:
displaying available options from async source
searching through available options based on given search criteria
clearing selected value
displaying preview image of each option
Let's use it now instead:
To use SimplePicker
we need to do the following things:
forward received
props
asvalue
andonChange
implement
getItems
method that's responsible for showing the list of available items to choose from based on entered search textimplement
getItemById
method that's responsible for fetching data about currently selected item
Compound types
Easyblocks allows you to return compound data, which is basically a data that consists of multiple "basic" data types. It means that instead of returning:
we can return:
Compound types are useful when working with root parameters.
Root parameters and template system
So far we've built a content that's static. Static images, static products, static text. Our content isn't reusable. What if we would like to build a product landing page, but feed it with different product each time? That's possible in Easyblocks thanks to root parameters. Root parameters allows you to define fields whose value can be supplied during the rendering of your content.
Let's use above product
type as our example and define a new component ProductPage
:
If we open the editor with search param rootComponent=ProductPage
we're going to see a product
field at the root level in the sidebar. Value for this field can be selected using one of the widgets specified in widgets
field.
If we add a Simple Text
component to the canvas, we will see a new option to change selected widget of the Text
value property
After selecting Document data
option, Text
property now would allow us to be connected to text
external data returned for the product
field.
To dynamically render the content with different products we have to overwrite the property $.product
of externalData
To dynamically set a value for root parameter we reference it by joining dollar sign and a name of root parameter ex. $.myRootParameter
For each product page, the content build using the editor is going to have different product data based od params.id
.
Last updated