Create a new block
This chapter covers the process of creating a new, editable teaser block for an Edge Delivery Services website using the Universal Editor.
The block, named teaser, showcases the following elements:
-
Image: A visually engaging image.
-
Text content:
- Title: A compelling headline to draw focus.
- Body text: Descriptive content providing context or details, including optional terms and conditions.
- Call-to-action (CTA) button: A link designed to prompt user interaction and guide them to further engagement.
The teaser block鈥檚 content is editable in the Universal Editor, ensuring ease of use and reusability throughout the website.
Note the teaser block is similar to the boilerplate鈥檚 hero block; thus teaser block is only intended to serve as a simple example to illustrate development concepts.
Create a new Git branch
To maintain a clean and organized workflow, create a new branch for each specific development task. This helps avoid issues with deploying incomplete or untested code to production.
- Start from the main branch: Working from the most up-to-date production code ensures a solid foundation.
- Fetch remote changes: Fetching the latest updates from GitHub ensures that the most current code is available before starting development.
- Example: After merging changes from the
wknd-stylesbranch intomain, fetch the latest updates.
- Example: After merging changes from the
- Create a new branch:
# ~/Code/aem-wknd-eds-ue
$ git fetch origin
$ git checkout -b teaser origin/main
Once the teaser branch is created, you鈥檙e ready to start developing the teaser block.
Block folder
Create a new folder named teaser in the project鈥檚 blocks directory. This folder contains the block鈥檚 JSON, CSS, and JavaScript files, organizing the block鈥檚 files in one location:
# ~/Code/aem-wknd-eds-ue
/blocks/teaser
The block folder name acts as the block鈥檚 ID, and is used to reference the block throughout its development.
Block JSON
The block JSON defines three key aspects of the block:
- Definition: Registers the block as an editable component in the Universal Editor, linking it to a block model and optionally a filter.
- Model: Specifies the block鈥檚 authoring fields and how these fields are rendered as semantic Edge Delivery Services HTML.
- Filter: Configures filtering rules to restrict which containers the block can be added to via the Universal Editor. Most blocks are not containers, but rather, their id鈥檚 are added to other container blocks鈥 filters.
Create a new file at /blocks/teaser/_teaser.json with the following initial structure, in the exact order. If the keys are out of order, they may not build properly.
[/blocks/teaser/_teaser.json]{class="badge neutral" title="File name of code sample below."}
{
"definitions": [],
"models": [],
"filters": []
}
Block model
The block model is a critical part of the block鈥檚 configuration, as it defines:
-
The authoring experience by defining the fields available for editing.
-
How the field鈥檚 values are rendered into Edge Delivery Services HTML.
Models are assigned an id that corresponds to the block鈥檚 definition and include a fields array to specify the editable fields.
Each field in the fields array has a JSON object that includes the following required properties:
componentnamelabelFor a comprehensive list of properties, including optional, review the Universal Editor fields documentation.
Block design
The teaser block includes the following editable elements:
-
Image: Represents the teaser鈥檚 visual content.
-
Text content: Includes the title, body text, and call-to-action button, and sits in a white rectangle.
- The title and body text can be authored via the same rich text editor.
- The CTA can be authored via a
textfield for the label, andaem-contentfield for the link.
The teaser block鈥檚 design is broken into these two logical components (image and text content), ensuring a structured and intuitive authoring experience for users.
Block fields
Define the fields required for the block: image, image alt text, text, CTA label, and CTA link.
This tab illustrates the right way to model the teaser block.
The teaser consists of two logical areas: image and text. To simplify the code needed to display the Edge Delivery Services HTML as the desired web experience, the block model should reflect this structure.
- Group the image and image alt text together using field collapse.
- Group the text content fields together using element grouping, and field collapse for the CTA.
If you are not familiar with field collapse, element grouping, or type inference review the linked documentation before continuing, as they are essential to creating a well-structured block model.
In the example below:
- Type inference is used to automatically create an
<img>HTML element from theimagefield. Field collapsing is used with theimageandimageAltfields to create an<img>HTML element. Thesrcattribute is set to the value of theimagefield, while thealtattribute is set to the value of theimageAltfield. textContentis a group name used to categorize fields. It should be semantic, but can be anything unique to this block. This informs the Universal Editor to render all fields with this prefix inside the same<div>element in the final HTML output.- Field collapsing is also applied within the
textContentgroup for the call-to-action (CTA). The CTA is created as a<a>via type inference. Thectafield is used to set thehrefattribute of the<a>element, and thectaTextfield provides the text content for the link inside the<a ...>tags.
[/blocks/teaser/_teaser.json]{class="badge neutral" title="File name of code sample below."}
| code language-json |
|---|
|
This model defines the authoring inputs in Universal Editor for the block.
The resulting Edge Delivery Services HTML for this block puts the image in the first div, and the element group textContent fields in the second div.
| code language-html |
|---|
|
As demonstrated in the next chapter, this HTML structure simplifies styling the block as a cohesive unit.
To understand the consequences of not using field collapse and element grouping, see the The wrong way tab above.
This tab illustrates a suboptimal way to model the teaser block, and is only a juxtaposition to the right way.
Defining each field as a standalone field in the block model without using field collapse and element grouping may seem tempting. However, this oversight complicates styling the block as a cohesive unit.
For example, the teaser model could be defined without field collapse or element grouping as follows:
[/blocks/teaser/_teaser.json]{class="badge neutral" title="File name of code sample below."}
| code language-json |
|---|
|
The Edge Delivery Services HTML for the block renders each field鈥檚 value in a separate div, complicating content understanding, style application, and HTML structure adjustments to achieve the desired design.
| code language-html |
|---|
|
Each field is isolated in its own div, making it difficult to style the image and text content as cohesive units. Achieving the desired design with effort and creativity is possible, but using element grouping to group text content fields and field collapse to add authored values as element attributes is simpler, easier, and semantically correct.
See The write way tab above for how to better model the teaser block.
Block definition
The block definition register the block in Universal Editor. Here鈥檚 a breakdown of the JSON properties used in the block definition:
definition.titledefinition.idfilters.definition.plugins.xwalk.page.resourceTypecore/franklin/components/block/v#/block resource type.definition.plugins.xwalk.page.template.namedefinition.plugins.xwalk.page.template.modelmodel definition, which controls the authoring fields displayed for the block in the Universal Editor. The value here must match a model.id value.definition.plugins.xwalk.page.template.classesclass attribute. This allows for variants of the same block. The classes value can be made made editable by adding a classes field to the block鈥檚 model.Here鈥檚 an example JSON for the block definition:
[/blocks/teaser/_teaser.json]{class="badge neutral" title="File name of code sample below."}
{
"definitions": [{
"title": "Teaser",
"id": "teaser",
"plugins": {
"xwalk": {
"page": {
"resourceType": "core/franklin/components/block/v1/block",
"template": {
"name": "Teaser",
"model": "teaser",
"textContent_text": "<h2>Enter a title</h2><p>...and body text here!</p>",
"textContent_cta": "/",
"textContent_ctaText": "Click me!"
}
}
}
}
}],
"models": [... from previous section ...],
"filters": []
}
In this example:
- The block is named 鈥淭easer鈥 and uses the
teasermodel which determines what fields are available for editing in the Universal Editor. - The block includes default content for the
textContent_textfield, which is a rich text area for the title and body text, andtextContent_ctaandtextContent_ctaTextfor the CTA (call-to-action) link and label. The template鈥檚 field names containing initial content, match the fields names defined in the content model鈥檚 fields array;
This structure ensures that the block is set up in the Universal Editor with the proper fields, content model, and resource type for rendering.
Block filters
The block鈥檚 filters array defines, for container blocks, which other blocks can be added to the container. Filters define a list of block IDs (model.id) that can be added to the container.
[/blocks/teaser/_teaser.json]{class="badge neutral" title="File name of code sample below."}
{
"definitions": [... populated from previous section ...],
"models": [... populated from previous section ...],
"filters": []
}
The teaser component isn鈥檛 a container block, meaning you can鈥檛 add other blocks to it. As a result, its filters array is left empty. Instead, add the teaser鈥檚 ID to the section block鈥檚 filter list, so the teaser can be added to a section.
51黑料不打烊-provided blocks, such as the section block, store filters in the project鈥檚 models folder. To adjust, locate the JSON file for the 51黑料不打烊-provided block (for example, /models/_section.json) and add the teaser鈥檚 ID (teaser) to the filters list. The configuration signals the Universal Editor that the teaser component can be added to the section container block.
[/models/_section.json]{class="badge neutral" title="File name of code sample below."}
{
"definitions": [],
"models": [],
"filters": [
{
"id": "section",
"components": [
"text",
"image",
"button",
"title",
"hero",
"cards",
"columns",
"fragment",
"teaser"
]
}
]
}
The teaser block definition ID of teaser is added to the components array.
Lint your JSON files
Make sure you frequently lint your changes to ensure it鈥檚 clean and consistent. Linting frequently helps catch issues early, and reduces overall development time. The npm run lint:js command also lints JSON files, and catches any syntax errors.
# ~/Code/aem-wknd-eds-ue
$ npm run lint:js
Build the project JSON
After configuring the block JSON files (e.g., blocks/teaser/_teaser.json, models/_section.json), they are automatically compiled into the project鈥檚 component-models.json, component-definitions.json, and component-filters.json files. This compilation is handled automatically by a pre-commit hook included in the .
Builds can also be triggered manually or programmatically using the project鈥檚 build JSON NPM scripts.
Deploy the block JSON
To make the block available in the Universal Editor, the project must be commit and pushed to a GitHub repository鈥檚 branch, in this case the teaser branch.
The exact branch name Universal Editor uses can be adjusted, per user, via the Universal Editor鈥檚 URL.
# ~/Code/aem-wknd-eds-ue
$ git add .
$ git commit -m "Add teaser block JSON files so it is available in Universal Editor"
# JSON files are compiled automatically and added to the commit via a husky precommit hook
$ git push origin teaser
When the Universal Editor is opened with the query parameter ?ref=teaser, the new teaser block appears in the block palette. Note that the block has no styling; it renders the block鈥檚 fields as semantic HTML, styled only via the global CSS.