aem-component-development
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAEM Component Development
AEM组件开发
AEM components are the building blocks of page content. Each component is a
node in the JCR that ties together:
cq:Component- HTL markup — the rendering template (file)
.html - Sling Model — server-side business logic (Java)
- Dialog — author UI for content editing ()
cq:dialog - Client libraries — CSS/JS for frontend behavior
- Edit config — authoring toolbar behavior ()
cq:editConfig
Prerequisite skill: This skill assumes HTL knowledge. Load the skill for
expression syntax, block statements, XSS contexts, and global objects.
htl-scriptingAEM组件是页面内容的构建块。每个组件都是JCR中的一个节点,关联以下内容:
cq:Component- HTL标记 — 渲染模板(文件)
.html - Sling Model — 服务器端业务逻辑(Java)
- 对话框 — 供作者编辑内容的UI()
cq:dialog - 客户端库 — 用于前端行为的CSS/JS
- 编辑配置 — 作者工具栏行为()
cq:editConfig
前置技能: 本技能假定您已掌握HTL知识。如需了解表达式语法、块语句、XSS上下文和全局对象,请加载技能。
htl-scriptingComponent File Structure
组件文件结构
Standard Maven archetype layout (Touch UI, modern AEM):
ui.apps/src/main/content/jcr_root/apps/<project>/components/<component-name>/
├── .content.xml ← cq:Component definition (title, group, supertype)
├── <component-name>.html ← HTL rendering script
├── _cq_dialog/
│ └── .content.xml ← Touch UI dialog (Granite UI)
├── _cq_editConfig/
│ └── .content.xml ← Edit behavior config
├── _cq_template/
│ └── .content.xml ← Default content on drag-and-drop
├── _cq_design_dialog/
│ └── .content.xml ← Policy/design dialog
└── clientlib/ ← Optional co-located clientlib
├── .content.xml
├── css.txt
├── js.txt
├── css/
└── js/
core/src/main/java/<package>/models/
└── <ComponentName>Model.java ← Sling ModelNote: Underscored directories () are the filesystem representation of JCR nodes
with colons (). The FileVault serialization requires this naming.
_cq_dialogcq:dialog标准Maven原型目录结构(Touch UI,现代AEM):
ui.apps/src/main/content/jcr_root/apps/<project>/components/<component-name>/
├── .content.xml ← cq:Component定义(标题、分组、父类型)
├── <component-name>.html ← HTL渲染脚本
├── _cq_dialog/
│ └── .content.xml ← Touch UI对话框(Granite UI)
├── _cq_editConfig/
│ └── .content.xml ← 编辑行为配置
├── _cq_template/
│ └── .content.xml ← 拖放时的默认内容
├── _cq_design_dialog/
│ └── .content.xml ← 策略/设计对话框
└── clientlib/ ← 可选的本地客户端库
├── .content.xml
├── css.txt
├── js.txt
├── css/
└── js/
core/src/main/java/<package>/models/
└── <ComponentName>Model.java ← Sling Model注意:带下划线的目录(如)是带有冒号的JCR节点(如)在文件系统中的表示形式。FileVault序列化要求使用此命名方式。
_cq_dialogcq:dialogComponent Definition (.content.xml
)
.content.xml组件定义(.content.xml
)
.content.xmlxml
<?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"
jcr:primaryType="cq:Component"
jcr:title="My Component"
jcr:description="A description for authors"
componentGroup="My Project - Content"
sling:resourceSuperType="core/wcm/components/text/v2/text"/>xml
<?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"
jcr:primaryType="cq:Component"
jcr:title="My Component"
jcr:description="A description for authors"
componentGroup="My Project - Content"
sling:resourceSuperType="core/wcm/components/text/v2/text"/>Key Properties
关键属性
| Property | Purpose |
|---|---|
| Display name in component browser |
| Tooltip in component browser |
| Grouping in component browser. Use |
| Inherit from another component (rendering, dialog, edit config) |
| |
| Coral UI icon name for the component browser |
| 2-char abbreviation if no icon |
| 属性 | 用途 |
|---|---|
| 组件浏览器中的显示名称 |
| 组件浏览器中的提示信息 |
| 组件浏览器中的分组。使用 |
| 继承另一个组件的功能(渲染、对话框、编辑配置) |
| 如果组件可包含子组件(如parsys),则设为 |
| 组件浏览器中使用的Coral UI图标名称 |
| 若无图标,可设置2字符的缩写 |
Agent Workflow: Creating a New Component
代理工作流:创建新组件
Step 1: Define the component node
步骤1:定义组件节点
Create with , title, group, and optionally
to extend an existing component.
.content.xmljcr:primaryType="cq:Component"sling:resourceSuperType创建文件,指定、标题、分组,可选设置以扩展现有组件。
.content.xmljcr:primaryType="cq:Component"sling:resourceSuperTypeStep 2: Create the Sling Model
步骤2:创建Sling Model
Write the Java model class in module. See references/sling-models.md.
core/java
@Model(adaptables = SlingHttpServletRequest.class,
adapters = MyComponent.class,
resourceType = "myproject/components/mycomponent",
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class MyComponentImpl implements MyComponent {
@ValueMapValue
private String title;
@ValueMapValue
private String description;
@Override
public String getTitle() { return title; }
@Override
public String getDescription() { return description; }
}在模块中编写Java模型类。详见references/sling-models.md。
core/java
@Model(adaptables = SlingHttpServletRequest.class,
adapters = MyComponent.class,
resourceType = "myproject/components/mycomponent",
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class MyComponentImpl implements MyComponent {
@ValueMapValue
private String title;
@ValueMapValue
private String description;
@Override
public String getTitle() { return title; }
@Override
public String getDescription() { return description; }
}Step 3: Create the HTL script
步骤3:创建HTL脚本
html
<sly data-sly-use.model="com.myproject.core.models.MyComponent"/>
<div class="cmp-mycomponent"
data-sly-test="${model.title || model.description}">
<h2 class="cmp-mycomponent__title"
data-sly-test="${model.title}">${model.title}</h2>
<div class="cmp-mycomponent__description"
data-sly-test="${model.description}">
${model.description @ context='html'}
</div>
</div>
<sly data-sly-test="${!model.title && !model.description && (wcmmode.edit || wcmmode.preview)}">
<div class="cq-placeholder" data-emptytext="My Component"></div>
</sly>html
<sly data-sly-use.model="com.myproject.core.models.MyComponent"/>
<div class="cmp-mycomponent"
data-sly-test="${model.title || model.description}">
<h2 class="cmp-mycomponent__title"
data-sly-test="${model.title}">${model.title}</h2>
<div class="cmp-mycomponent__description"
data-sly-test="${model.description}">
${model.description @ context='html'}
</div>
</div>
<sly data-sly-test="${!model.title && !model.description && (wcmmode.edit || wcmmode.preview)}">
<div class="cq-placeholder" data-emptytext="My Component"></div>
</sly>Step 4: Create the dialog
步骤4:创建对话框
See references/dialogs.md for full Granite UI field reference.
xml
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
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"
jcr:primaryType="nt:unstructured"
jcr:title="My 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">
<properties jcr:primaryType="nt:unstructured"
jcr:title="Properties"
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">
<title jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="Title"
name="./title"/>
<description jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textarea"
fieldLabel="Description"
name="./description"/>
</items>
</column>
</items>
</columns>
</items>
</properties>
</items>
</tabs>
</items>
</content>
</jcr:root>完整的Granite UI字段参考详见references/dialogs.md。
xml
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
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"
jcr:primaryType="nt:unstructured"
jcr:title="My 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">
<properties jcr:primaryType="nt:unstructured"
jcr:title="Properties"
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">
<title jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="Title"
name="./title"/>
<description jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textarea"
fieldLabel="Description"
name="./description"/>
</items>
</column>
</items>
</columns>
</items>
</properties>
</items>
</tabs>
</items>
</content>
</jcr:root>Step 5: Add client library (if needed)
步骤5:添加客户端库(如需)
See references/clientlibs.md.
详见references/clientlibs.md。
Step 6: Configure edit behavior (if needed)
步骤6:配置编辑行为(如需)
xml
<?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"
jcr:primaryType="cq:EditConfig"
cq:actions="[edit,delete,insert,copymove]"
cq:layout="editbar"
cq:dialogMode="floating">
<cq:listeners jcr:primaryType="cq:EditListenersConfig"
afteredit="REFRESH_PAGE"
afterinsert="REFRESH_PAGE"/>
</jcr:root>xml
<?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"
jcr:primaryType="cq:EditConfig"
cq:actions="[edit,delete,insert,copymove]"
cq:layout="editbar"
cq:dialogMode="floating">
<cq:listeners jcr:primaryType="cq:EditListenersConfig"
afteredit="REFRESH_PAGE"
afterinsert="REFRESH_PAGE"/>
</jcr:root>Extending Existing Components
扩展现有组件
Use to inherit everything from a parent:
sling:resourceSuperTypexml
<jcr:root ...
jcr:primaryType="cq:Component"
jcr:title="Custom Text"
sling:resourceSuperType="core/wcm/components/text/v2/text"
componentGroup="My Project"/>What you inherit automatically:
- HTL rendering scripts (resolved by Sling resource type hierarchy)
- Dialogs (can overlay individual fields via Sling Resource Merger)
- Edit config, descriptions, icons
To overlay a dialog field, create only the nodes you need to change under
and set on the dialog root. The Sling Resource Merger merges your
changes with the parent.
_cq_dialog/sling:resourceSuperType使用继承父组件的所有功能:
sling:resourceSuperTypexml
<jcr:root ...
jcr:primaryType="cq:Component"
jcr:title="Custom Text"
sling:resourceSuperType="core/wcm/components/text/v2/text"
componentGroup="My Project"/>自动继承的内容:
- HTL渲染脚本(通过Sling资源类型层级解析)
- 对话框(可通过Sling资源合并器覆盖单个字段)
- 编辑配置、描述、图标
要覆盖对话框字段,只需在下创建需要修改的节点,并在对话框根节点设置。Sling资源合并器会将您的修改与父组件的配置合并。
_cq_dialog/sling:resourceSuperTypeCore Components
核心组件
Always prefer extending AEM Core Components
over building from scratch. They provide:
- Production-tested, accessible, SEO-friendly markup
- BEM CSS class naming ()
cmp-<name>__<element>--<modifier> - Sling Model exporters for JSON/SPA
- Style System support
- Adobe Client Data Layer integration
Common Core Components to extend:
core/wcm/components/text/v2/textcore/wcm/components/image/v3/imagecore/wcm/components/title/v3/titlecore/wcm/components/teaser/v2/teasercore/wcm/components/list/v4/listcore/wcm/components/container/v1/containercore/wcm/components/page/v3/page
优先扩展AEM核心组件而非从零开始构建。核心组件提供:
- 经过生产验证、可访问、对SEO友好的标记
- BEM CSS类命名规范()
cmp-<name>__<element>--<modifier> - 用于JSON/SPA的Sling Model导出器
- 样式系统支持
- Adobe客户端数据层集成
常见的可扩展核心组件:
core/wcm/components/text/v2/textcore/wcm/components/image/v3/imagecore/wcm/components/title/v3/titlecore/wcm/components/teaser/v2/teasercore/wcm/components/list/v4/listcore/wcm/components/container/v1/containercore/wcm/components/page/v3/page
Edit Placeholder Pattern
编辑占位符模式
Components MUST render something visible in edit mode even when empty:
html
<!--/* Reusable Core Components placeholder template */-->
<sly data-sly-use.template="core/wcm/components/commons/v1/templates.html"
data-sly-call="${template.placeholder @ isEmpty=!model.hasContent}"/>Or manual fallback:
html
<div class="cq-placeholder" data-emptytext="${component.properties.jcr:title}"
data-sly-test="${(wcmmode.edit || wcmmode.preview) && isEmpty}"></div>组件在编辑模式下即使为空,也必须渲染可见内容:
html
<!--/* 可复用的核心组件占位符模板 */-->
<sly data-sly-use.template="core/wcm/components/commons/v1/templates.html"
data-sly-call="${template.placeholder @ isEmpty=!model.hasContent}"/>或手动回退方案:
html
<div class="cq-placeholder" data-emptytext="${component.properties.jcr:title}"
data-sly-test="${(wcmmode.edit || wcmmode.preview) && isEmpty}"></div>Content Template (_cq_template/
)
_cq_template/内容模板(_cq_template/
)
_cq_template/Pre-populates the component's content node when dragged onto a page:
xml
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="nt:unstructured"
title="Default Title"
description="Edit this component"/>当组件被拖放到页面时,自动预填充组件的内容节点:
xml
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="nt:unstructured"
title="Default Title"
description="Edit this component"/>Resource Type Resolution
资源类型解析
Sling resolves components by on the content node:
sling:resourceType- Content node has
sling:resourceType = "myproject/components/hero" - Sling looks for
/apps/myproject/components/hero/hero.html - If not found, checks chain
sling:resourceSuperType - Falls back to search path
/libs/
Script resolution order for a resource type :
myproject/components/hero- (matches component name)
hero.html - (matches extension)
html.html - (matches method + extension)
GET.html - Then walks up the chain
sling:resourceSuperType
Sling通过内容节点上的解析组件:
sling:resourceType- 内容节点的
sling:resourceType = "myproject/components/hero" - Sling查找
/apps/myproject/components/hero/hero.html - 若未找到,则检查链
sling:resourceSuperType - 最后回退到搜索路径
/libs/
资源类型的脚本解析顺序:
myproject/components/hero- (匹配组件名称)
hero.html - (匹配扩展名)
html.html - (匹配方法+扩展名)
GET.html - 然后遍历链
sling:resourceSuperType
Critical Rules
重要规则
- Always use Touch UI () — Classic UI dialogs are deprecated.
cq:dialog - Prefer Sling Models over — Sling Models are testable, cacheable, and the standard for AEM as a Cloud Service.
WCMUsePojo - Never modify — always overlay in
/libs. Use Sling Resource Merger for partial overrides./apps - Always render an edit placeholder when component has no content.
- Use BEM naming for CSS classes: .
cmp-<component>__<element>--<modifier> - Set or the component won't appear in the authoring UI.
componentGroup - Store dialog field values with prefix in
./attribute (e.g.,name) to write relative to the component's content node.name="./title" - Extend Core Components before building from scratch.
- Client libraries under need
/appsto be served viaallowProxy=true./etc.clientlibs/
- 始终使用Touch UI()—— 经典UI对话框已被弃用。
cq:dialog - 优先使用Sling Models而非—— Sling Models可测试、可缓存,是AEM as a Cloud Service的标准方案。
WCMUsePojo - 切勿修改目录—— 始终在
/libs目录中进行覆盖。使用Sling资源合并器进行部分覆盖。/apps - 组件为空时必须渲染编辑占位符。
- CSS类使用BEM命名规范:。
cmp-<component>__<element>--<modifier> - 设置—— 否则组件不会在作者UI中显示。
componentGroup - 对话框字段值的存储—— 在属性中使用
name前缀(如./),以便将值写入组件的内容节点。name="./title" - 优先扩展核心组件而非从零开始构建。
- 下的客户端库需要设置
/apps才能通过allowProxy=true访问。/etc.clientlibs/
Reference Files
参考文档
- references/dialogs.md — Touch UI dialog structure, Granite UI field types, tabs, validation
- references/clientlibs.md — Client library folder setup, categories, dependencies, HTL inclusion
- references/sling-models.md — Sling Model annotations, injection strategies, adapters, testing
- references/dialogs.md — Touch UI对话框结构、Granite UI字段类型、标签页、验证
- references/clientlibs.md — 客户端库文件夹设置、分类、依赖、HTL引入方式
- references/sling-models.md — Sling Model注解、注入策略、适配器、测试