Day 14 of 40
WKND: Component Basics
Authoring dialogs, how values persist, and your first Sling Model
By the end of today you should be able to
- Describe the four files that make up a component and what each does
- Explain how a dialog field maps to a JCR property
- Trace a value from dialog input, through the repository, to rendered markup
- Explain what cq:dialog, cq:editConfig and componentGroup control
Anatomy of a component
A component is a folder under /apps/<appId>/components/. At most it contains:
.content.xml— thecq:Componentnode: title, group,sling:resourceSuperType.<name>.html— the HTL script that renders it._cq_dialog/.content.xml— the authoring dialog, defined in Granite UI._cq_editConfig.xml— editing behaviour: drop targets, listeners, toolbar actions.
A proxy component has only the first. A fully custom component has all four plus a Sling Model in
core. Everything is content — even the dialog is just nodes, which is why you can inspect
and modify it in CRXDE.
The authoring round trip
This is the loop worth internalising, because almost every component bug lives somewhere along it:
- An author drops the component onto a page. AEM creates a node with
sling:resourceType = "wknd/components/title". - They open the dialog. Granite UI renders the fields from
_cq_dialog. - Each field has a
namelike./jcr:title. The leading./means "relative to this component's node". - On save, a POST goes to the component's node and the Sling POST servlet writes
jcr:title = "Welcome"as a property. - On render, the Sling Model reads that property and HTL outputs it.
A dialog field named ./jcr:title becomes a property called jcr:title on the component node. No mapping layer, no schema. If a value is not showing up, open CRXDE and look at the node — you will usually see immediately that the property is missing, misnamed, or the wrong type.
A dialog, concretely
Granite UI dialogs are verbose but mechanical. Stripped to essentials:
<jcr:root jcr:primaryType="nt:unstructured"
sling:resourceType="cq/gui/components/authoring/dialog"
jcr:title="Title">
<content sling:resourceType="granite/ui/components/coral/foundation/container">
<items>
<tabs sling:resourceType="granite/ui/components/coral/foundation/tabs">
<items>
<properties jcr:title="Properties">
<items>
<title
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="Title"
name="./jcr:title"/>
</items>
</properties>
</items>
</tabs>
</items>
</content>
</jcr:root>
Field types you will use constantly:
form/textfield,form/textarea,form/numberfieldform/pathfield— pick a page or assetform/select— a dropdown, with options as child nodes or from a datasourceform/checkbox— note it needs a companionform/hiddenfield with@Deleteso unchecking actually removes the propertyform/multifield— a repeating group, stored as numbered child nodes
cq:editConfig
_cq_editConfig.xml controls how the component behaves in the editor, not how it
renders. Two things you will actually reach for:
- Drop targets — let an author drag an asset from the DAM directly onto the component, writing to a named property.
- Refresh behaviour —
cq:listenerswithafteredit="REFRESH_PAGE"forces a full page reload after editing, which you need when a component affects page-level markup.
Debugging the round trip
When a component shows nothing, walk the loop in order rather than guessing:
- Does the node exist, with the right
sling:resourceType? (CRXDE) - Did the dialog write the property, with the expected name? (CRXDE)
- Is the Sling Model registered and adapting? (
/system/console/slingmodels) - Is the HTL reading the field name you think it is?
Nine times out of ten step 2 answers it — a dialog field whose name lost its ./ prefix, or a typo in the property name.
Dialog field name → JCR property → Sling Model getter → HTL expression. Four links; when something is empty, find the broken link rather than rewriting the component.
Watch
Adobe's own videos for this topic. They load only when you press play.
Read on Experience League
The primary sources these notes are drawn from.
Your notes
Saved automatically to this browser.
Check yourself
10 questions on today's material. 80% to pass.