The Block Editor field in dotCMS is a new rich content editor that allows you to create your content as building blocks.
Every element inside your editor is a block that you can add, edit, drag, and drop to reorder and delete.
Block Types
Block types currently include the following:
Block | System Name(s) | Description |
---|---|---|
Paragraph | paragraph | Default block type, for text and formatting marks |
Heading | heading1 heading2 heading3 | Several levels of section headings. |
List | bulletList orderedList listItem | Ordered or unordered lists |
Block Quote | blockQuote | For paragraph-length quotations |
Code Block | codeBlock | Monospaced preformatted section |
Horizontal Line | horizontalRule | A line for dividing vertical sections |
Image | dotImage | Fully compatible with copy/paste or drag & drop insertion, image blocks are stored as dotAssets |
Contentlet | (varies) | Special blocks consisting of Content Type instances defined elsewhere in dotCMS, allowing for the creation of rich and dynamic content |
Block Formatting
You can style your blocks with bold, italic, underline, and strikeout marks.
You can alter the alignment of blocks or transform them into other blocks. A paragraph can be turned into a heading, a blockquote, and so on, with a just a simple dropdown selection.
JSON Object
The block content gets saved as a JSON object with all the information you need to render it in your page. For example, say your Block Editor's content consists of a single paragraph containing “Hello World”; its final object would look like this:
{
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"marks": [
{
"type": "bold"
}
],
"text": "Hello"
},
{
"type": "text",
"text": " World"
}
]
}
]
}
Each block object has two important properties:
type
: a string with the name of the blockcontent
: an array of blocks containing the content
The JSON output always begins with a type of doc
, which is the parent block. The content
property contains all the child-block data — i.e., the content itself.
Within the content blocks, there are further conventions to note, the most important of which is the distinction between text
and non-text block types.
The text
Type
A content
type of text
specifies the raw text of the block. For example, a heading, paragraph, or blockquote block will contain content of type text
. These members may additionally contain a property named marks
, which contain formatting information: bold, italic, underline, etc.
Non-Text Types
Other blocks, such as image or contentlet blocks, will store in their content
all the properties necessary to render them. For an image block, this includes its path, width, and height; for a contentlet, it will have all the information about the contentlet field, including the iNode, identifier, etc.
Rendering Content
VTL Rendering
To render a Block Editor field from the dotCMS admin panel, call the toHtml()
velocity method on the contentlet object:
$content.blockFieldName.toHtml()
This will render the content of the field into basic HTML.
For example:
- Paragraphs:
<p>Content</p>
- Headings:
<h1>Content</h1>
<h2>Content</h2>
<h3>Content</h3>
- List:
<ul><li>Content</li></ul>
- Ordered
<ol><li>Content</li></ol>
- Unordered
<ul><li>Content</li></ul>
- Ordered
- Horizontal Line:
<hr>
Customizing Block HTML Rendering
dotCMS permits customization of how blocks are rendered as HTML. Simply create VTL files named for the block they override, and then define the rendering behavior within.
For a list of these names, see the “System Name” column of the table under Block Types). Additionally, there are two other overridable type names:
text
— described under Thetext
TypehardBreak
— allows the override of line-break behavior.
Finally, call the toHtml()
method, passing as an argument the path to the folder containing the overriding file or files.
Customization Example: Heading 1
To modify the Heading 1 blocks, first create a file named heading1.vtl
inside the /application/storyblock
folder.
Add the following code to the file:
#parse( "static/storyblock/marks-macro.vtl" )
<h1 class="text-heading">
#foreach($content in $item.content)
#renderText($content)
#end
</h1>
In this code:
- We import the macros.
- We add the HTML
<h1>
tag with any class or attributes we need. - In the
foreach
, we iterate over all the items inside the content and render the text using therenderText
macro that will handle formatting marks automatically.
Finally, update your container code to pass the folder with the VTL you created to the toHtml()
method like this:
$content.blockFieldName.toHtml('/application/storyblock/')
dotCMS will look for VTL files for each block in the storyblock folder and fall back to the default rendering behavior if no custom file is found.
Headless Rendering
Headless rendering of the Block Editor begins with an API call to fetch the JSON object. This call may be made via a variety of APIs, including the Page API, GraphQL, Content API, Elasticsearch API, or any other API capable of calling a contentlet containing a Block Editor field.
For example, a Page API call would be a straightforward retrieval using this address template:
https://{server_address}/api/v1/page/json/{page_path}
Below is a demo page and its corresponding Page API path. Please note that the Page API requires being signed in (user:admin@dotcms.com
, password:admin
):
…/blog/post/french-polynesia-everything-you-need-to-know …/api/v1/page/json/blog/post/french-polynesia-everything-you-need-to-know
On the linked page's output, the blogContent
field begins as all Block Editor JSON objects do: with "type": "doc"
. Its second member, content
, contains a nested array of all the child blocks — i.e., everything entered in the Block Editor.
Once the JSON object is parsed, your options for rendering are virtually limitless. Grab a Javascript framework of your choice and get creative!
Here's one compact example of rendering blocks using React.