Description

A content block is a resource that renders static authored content — headings, paragraphs, lists, tables, and images — without requiring a SQL query. The content is written once in the visual editor and stored in the ud_content_blocks database table. At render time the framework reads the stored content and outputs HTML.

Content blocks are useful whenever you need to place editorial content alongside data-driven blocks on a page: introductory text above a table, an image next to a chart, a section heading inside a grid.


Database table

Before using content blocks you must create the following table in your database:

CREATE TABLE ud_content_blocks (
  cb_id      INT AUTO_INCREMENT PRIMARY KEY,
  cb_name    VARCHAR(255) NOT NULL UNIQUE,
  cb_type    VARCHAR(50)  NOT NULL,
  cb_content JSON         NOT NULL,
  cb_updated DATETIME,
  cb_created DATETIME
);

Resource file

A content block resource file is minimal. It declares the resource name and type. The actual content lives in the database row whose cb_name matches the resource name.

{
  "name": "intro-paragraph",
  "metadata": { "type": "contentblock", "version": "1" },
  "allowedgroups": [ "admingroup" ]
}

Register the file path in your resource index and register the template class:

$jsonResourceTemplates['contentblock'] =
    \Fabiom\UglyDuckling\Framework\ContentBlocks\ContentBlockJsonTemplate::class;

Block sub-types

heading

Renders an HTML heading tag (<h1><h6>).

{ "level": 2, "text": "Welcome to the dashboard" }
Property Type Description
level integer 1–6 Heading level
text string Heading text

paragraph

Renders a <p> tag.

{ "text": "This section shows the latest activity across all projects." }
Property Type Description
text string Paragraph text

list

Renders a <ul> or <ol> tag with <li> items.

{ "ordered": false, "items": ["First item", "Second item", "Third item"] }
Property Type Description
ordered boolean true for a numbered list, false for a bullet list
items array of strings List items

statictable

Renders a <table> with fixed headers and rows.

{
  "headers": ["Name", "Role", "Location"],
  "rows": [
    ["Alice", "Developer", "Rome"],
    ["Bob",   "Designer",  "Milan"]
  ]
}
Property Type Description
headers array of strings Column header labels
rows array of arrays Each inner array is one row of cell values

image

Renders an <img> tag.

{ "src": "uploads/images/banner.jpg", "alt": "Project banner", "cssclass": "img-fluid" }
Property Type Description
src string Path to the image file (relative to the application public root)
alt string Alternative text for accessibility
cssclass string CSS class(es) applied to the <img> tag

Using a content block inside a grid

Place the content block resource name in a grid panel exactly like any other resource:

{
  "name": "homepage-grid",
  "metadata": { "type": "grid", "version": "1" },
  "allowedgroups": [ "admingroup" ],
  "cssclass": "row",
  "panels": [
    { "id": "panel1", "cssclass": "col-12",   "resource": "intro-paragraph" },
    { "id": "panel2", "cssclass": "col-md-8", "resource": "articlestable" },
    { "id": "panel3", "cssclass": "col-md-4", "resource": "sidebar-image" }
  ]
}

Editing content

Content blocks are authored through the Visual Editor. You can also insert or update a row directly in the database:

INSERT INTO ud_content_blocks (cb_name, cb_type, cb_content, cb_updated, cb_created)
VALUES (
  'intro-paragraph',
  'paragraph',
  '{"text": "Welcome to the system."}',
  NOW(), NOW()
)
ON DUPLICATE KEY UPDATE
  cb_type    = VALUES(cb_type),
  cb_content = VALUES(cb_content),
  cb_updated = NOW();