Session 4 β Components, dialogs & HTL
Purpose: Learn the anatomy of an AEM component: HTL render script, dialog, and how authors configure instances.
Who this page is for
| Audience | Why it matters to you |
|---|---|
| Frontend engineers | Your primary deliverable in AEM |
| Backend engineers | You will pair models with these |
Component anatomy
An AEM component is a folder in /apps. For the PHI plan-card:
/apps/phi-academy/components/plancard/
βββ plancard.html β HTL render script (the "JSX")
βββ _cq_dialog/.content.xmlβ author dialog (the "props form")
βββ .content.xml β component metadata (title, group, superType)
βββ clientlibs/ β optional component-scoped CSS/JS
| Piece | React equivalent |
|---|---|
| HTL script | The component's JSX |
| Dialog | Storybook controls / props form β but for authors, persisted to JCR |
sling:resourceSuperType | extends a base component |
| Component group | Palette category authors pick from |
HTL in five expressions
HTL (HTML Template Language) is intentionally logic-poor β think server-side JSX with escaping on by default:
<div class="plan-card" data-sly-use.model="com.academy.phi.models.PlanCardModel">
<h2>${model.title}</h2> <!-- auto XSS-escaped -->
<p data-sly-test="${model.subtitle}">${model.subtitle}</p> <!-- conditional -->
<ul data-sly-list.benefit="${model.benefits}"> <!-- iteration -->
<li class="${benefit.covered ? 'tick' : 'cross'}">${benefit.label}</li>
</ul>
<a href="${model.ctaLink @ extension='html'}">${model.ctaText}</a> <!-- context-aware output -->
</div>
| HTL | JSX equivalent |
|---|---|
data-sly-use.model="β¦" | const model = usePlanCard() |
${model.title} | {model.title} (escaped, like JSX) |
data-sly-test | {condition && β¦} |
data-sly-list | {items.map(β¦)} |
data-sly-resource | Rendering a child component |
@ context='β¦' | Choosing the escaping strategy (no JSX equivalent β HTL is stricter) |
No arbitrary logic is allowed in HTL β anything conditional beyond simple tests belongs in the Sling Model (Session 5). That is the platform enforcing the "dumb view, smart hook" split you already practice.
Dialogs
Dialogs are XML definitions of Granite/Coral form fields. The values authors enter are written as properties on the component's content node β which your model then reads. Field types cover text, rich text, path pickers, asset pickers, checkboxes, multifields (repeating rows β used for the benefits table).
Authoring safety rules
- Every field the dialog exposes must render safely when empty (new instances start blank).
- Provide sensible placeholders via the component's
cq:editConfig/empty placeholder pattern. - Never assume an author fills fields in order, or at all.