Component Dialogs
1. Basic Dialog Structure
On Touch UI, all dialogs follow a strict nested XML structure built using Granite UI libraries. Below is the basic skeleton:
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
xmlns:granite="http://www.adobe.com/jcr/granite/1.0"
xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
jcr:primaryType="nt:unstructured"
jcr:title="Component Name"
sling:resourceType="cq/gui/components/authoring/dialog">
<content jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<!-- Declare Tabs or Fields here -->
</items>
</content>
</jcr:root>
This file must be located at _cq_dialog/.content.xml inside the component directory.
To understand data storage mechanics, consider the interaction flow between UI and JCR:
Below are common Granite UI field types (widgets), serving as building blocks for Dialogs.
Textfield (Single-line Text)
<title jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="Title"
fieldDescription="Enter title for component"
name="./title"
required="{Boolean}true"
maxlength="100"/>
Textarea (Multi-line Text)
<description jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textarea"
fieldLabel="Description"
name="./description"
rows="5"/>
Rich Text Editor (RTE)
<richText jcr:primaryType="nt:unstructured"
sling:resourceType="cq/gui/components/authoring/dialog/richtext"
fieldLabel="Content"
name="./text"
useFixedInlineToolbar="{Boolean}true"/>
Number Field
<count jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/numberfield"
fieldLabel="Quantity"
name="./count"
min="{Long}1" max="{Long}100" step="{Long}1" value="{Long}10"/>
Checkbox
<featured jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/checkbox"
text="Featured"
name="./featured"
value="{Boolean}true"/>
Select Dropdown
<alignment jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/select"
fieldLabel="Alignment"
name="./alignment">
<items jcr:primaryType="nt:unstructured">
<left jcr:primaryType="nt:unstructured" text="Left" value="left" selected="{Boolean}true"/>
<center jcr:primaryType="nt:unstructured" text="Center" value="center"/>
<right jcr:primaryType="nt:unstructured" text="Right" value="right"/>
</items>
</alignment>
Path Browser (Select Page or Asset)
<linkPath jcr:primaryType="nt:unstructured"
sling:resourceType="cq/gui/components/coral/common/form/pagefield"
fieldLabel="Path"
fieldDescription="Select a page"
name="./linkPath"
rootPath="/content"/>
filter Parameter Table:
Image Upload
<file jcr:primaryType="nt:unstructured"
sling:resourceType="cq/gui/components/authoring/dialog/fileupload"
fieldLabel="Image"
name="./file"
fileNameParameter="./fileName"
fileReferenceParameter="./fileReference"
mimeTypes="[image/gif,image/jpeg,image/png,image/tiff,image/svg+xml]"/>
Hidden Field
<componentType jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/hidden"
name="./componentType"
value="customHero"/>
Date Picker & Color Picker
<eventDate jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/datepicker"
fieldLabel="Event Date"
name="./eventDate"
type="datetime"/>
<bgColor jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/colorpicker"
fieldLabel="Background Color"
name="./bgColor"/>
3. UI Organization using Tabs
For complex components, grouping fields into Tabs optimizes Authoring experience.
<tabs jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/tabs"
maximized="{Boolean}true">
<items jcr:primaryType="nt:unstructured">
<contentTab jcr:primaryType="nt:unstructured"
jcr:title="Content"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<!-- Content fields -->
</items>
</contentTab>
<styleTab jcr:primaryType="nt:unstructured"
jcr:title="Style"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<!-- Style fields -->
</items>
</styleTab>
</items>
</tabs>
Standard Tab Division Pattern:
4. Multifield Mechanics (Data Arrays)
Multifield allows authors to generate repeating field groups (e.g., Carousel Slides, Link Lists).
The key attribute is composite="{Boolean}true". When enabled, AEM saves each multifield item as an independent child node containing its own properties. Without this attribute, data is saved as a String Array (applicable only for multifields containing a single Textfield).
<links jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/multifield"
fieldLabel="Link List"
composite="{Boolean}true">
<field jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container"
name="./links">
<items jcr:primaryType="nt:unstructured">
<label jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="Label" name="./label" required="{Boolean}true"/>
<url jcr:primaryType="nt:unstructured"
sling:resourceType="cq/gui/components/coral/common/form/pagefield"
fieldLabel="URL" name="./url" required="{Boolean}true"/>
<openInNewTab jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/checkbox"
text="Open in new tab" name="./openInNewTab" value="{Boolean}true"/>
</items>
</field>
</links>
JCR structure when using composite=true:
5. Reading Values via Sling Models
When configuring Image Upload with fileReferenceParameter="./fileReference", the selected DAM Asset path is saved as a String property.
In Sling Models, map this value using @ValueMapValue:
@Model(adaptables = Resource.class)
public class HeroModel {
@ValueMapValue
private String fileReference; // DAM Path, e.g. "/content/dam/mysite/hero.jpg"
public String getFileReference() {
return fileReference;
}
}
6. Understanding the name Attribute
The name attribute determines the exact JCR location where data will be persisted:
The ./ prefix specifies a relative path relative to the active content resource being edited.
7. Comprehensive Structure: Hero Component Dialog
Below is reference XML source code for a Hero banner dialog including column layout, tabs, and full field types:
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
xmlns:granite="http://www.adobe.com/jcr/granite/1.0"
xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
jcr:primaryType="nt:unstructured"
jcr:title="Hero Component"
sling:resourceType="cq/gui/components/authoring/dialog">
<content jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<tabs jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/tabs"
maximized="{Boolean}true">
<items jcr:primaryType="nt:unstructured">
<!-- Content Tab -->
<contentTab jcr:primaryType="nt:unstructured"
jcr:title="Content"
sling:resourceType="granite/ui/components/coral/foundation/container"
margin="{Boolean}true">
<items jcr:primaryType="nt:unstructured">
<columns jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"
margin="{Boolean}true">
<items jcr:primaryType="nt:unstructured">
<column jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<heading jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="Title" name="./heading" required="{Boolean}true"/>
<subheading jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textarea"
fieldLabel="Subtitle" name="./subheading" rows="3"/>
<file jcr:primaryType="nt:unstructured"
sling:resourceType="cq/gui/components/authoring/dialog/fileupload"
fieldLabel="Background Image" name="./file" fileReferenceParameter="./fileReference"/>
<ctaLabel jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="CTA Label" name="./ctaLabel"/>
</items>
</column>
</items>
</columns>
</items>
</contentTab>
<!-- Style Tab -->
<styleTab jcr:primaryType="nt:unstructured"
jcr:title="Style"
sling:resourceType="granite/ui/components/coral/foundation/container"
margin="{Boolean}true">
<items jcr:primaryType="nt:unstructured">
<columns jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"
margin="{Boolean}true">
<items jcr:primaryType="nt:unstructured">
<column jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<overlay jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/select"
fieldLabel="Overlay" name="./overlay">
<items jcr:primaryType="nt:unstructured">
<none jcr:primaryType="nt:unstructured" text="None" value="none"/>
<light jcr:primaryType="nt:unstructured" text="Light" value="light"/>
<dark jcr:primaryType="nt:unstructured" text="Dark" value="dark" selected="{Boolean}true"/>
</items>
</overlay>
<fullWidth jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/checkbox"
text="Full Width" name="./fullWidth" value="{Boolean}true"/>
</items>
</column>
</items>
</columns>
</items>
</styleTab>
</items>
</tabs>
</items>
</content>
</jcr:root>
8. Dynamic Visibility (Conditional Show/Hide)
A common project requirement is to toggle visibility of fields based on another field's value. Granite UI provides built-in client library cq-dialog-dropdown-showhide.
Example: Display "Custom URL" field only when selecting "Custom Link" in Dropdown.
<!-- 1. Control Field (Select Dropdown) -->
<linkType jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/select"
fieldLabel="Link Type"
name="./linkType">
<granite:data jcr:primaryType="nt:unstructured"
cq-dialog-dropdown-showhide-target=".hero-link-options"/>
<items jcr:primaryType="nt:unstructured">
<none jcr:primaryType="nt:unstructured" text="None" value="none"/>
<page jcr:primaryType="nt:unstructured" text="Internal Page" value="page"/>
<custom jcr:primaryType="nt:unstructured" text="Custom URL" value="custom"/>
</items>
</linkType>
<!-- 2. Dependent Field: Shown only when linkType = "page" -->
<pageContainer jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<granite:data jcr:primaryType="nt:unstructured"
showhidetargetvalue="page"/>
<items jcr:primaryType="nt:unstructured">
<linkPage jcr:primaryType="nt:unstructured"
sling:resourceType="cq/gui/components/coral/common/form/pagefield"
fieldLabel="Select Page"
name="./linkPage"/>
</items>
</pageContainer>
<!-- 3. Dependent Field: Shown only when linkType = "custom" -->
<customContainer jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<granite:data jcr:primaryType="nt:unstructured"
showhidetargetvalue="custom"/>
<items jcr:primaryType="nt:unstructured">
<linkCustom jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="Custom URL"
name="./linkCustom"/>
</items>
</customContainer>
Add CSS class hero-link-options to target containers (or wrap containers in granite:class="hero-link-options").
Summary
- Touch UI Dialogs are configured via XML in
_cq_dialog/.content.xml.
- The
./ prefix in name stores properties on the current component content node.
composite="{Boolean}true" is required for multifields to store entries as child nodes.
- Use
cq-dialog-dropdown-showhide for conditional field toggling.