For AI agents: the complete documentation index is available at https://nhanbe.id.vn/llms.txt, the full documentation bundle is available at https://nhanbe.id.vn/llms-full.txt, and this page is available as Markdown at https://nhanbe.id.vn/aem/foundation/component-dialogs.md.

Basic Dialog Structure On Touch UI, all dialogs follow a strict nested XML structure built using Granite UI libraries.

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:

2. Core Field Types (Common Widgets)

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:

filter ValueVisibility Scope
hierarchyNotFileDisplay Page structures only (exclude Assets)
nosystemHide system paths
(unspecified)Display all paths

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:

TabTypical Fields
ContentTitle, text, images (Core content).
StyleAlignment, colors, size (Visual styling configuration).
AdvancedHTML ID, CSS class, Accessibility attributes (Technical settings).

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:

name SyntaxStorage Location in JCR
./titleDirectly on component content node (property named title).
./jcr:titleDirectly on content node (using standard jcr namespace).
./links/item0/labelNested inside sub-node links/item0.

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.