aem-component-development について
開発者やコーディングエージェント向けの Adobe Experience Manager コンポーネント開発スキルです。構成、実装手順、継承、編集時の指針を扱います。
主な機能
- 01コンポーネントのファイル構成と定義
- 02Sling Model と HTL の実装
- 03Touch UI ダイアログの指針
- 04Core Component の継承パターン
- 05編集プレースホルダーと編集動作
活用シーン
- 01AEM コンポーネントの新規作成
- 02既存 Core Component の拡張
- 03ダイアログと編集動作の設定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ headwirecom/ aem-agent-skills --skill aem-component-developmentインストール後、Claude Code で/aem-component-developmentを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/clientlibs.mddialogs.mdsling-models.md詳細
AEM コンポーネント開発
AEM コンポーネントは、ページコンテンツを構成する基本要素です。各コンポーネントは、次の要素をまとめる JCR 内の cq:Component ノードです。
- HTL マークアップ — レンダリングテンプレート(
.htmlファイル) - Sling Model — サーバー側のビジネスロジック(Java)
- ダイアログ — コンテンツ編集用のオーサリング UI(
cq:dialog) - クライアントライブラリ — フロントエンドの動作に使用する CSS/JS
- 編集設定 — オーサリングツールバーの動作(
cq:editConfig)
前提となるスキル: このスキルでは HTL の知識を前提とします。式の構文、ブロック文、XSS コンテキスト、グローバルオブジェクトについては、htl-scripting スキルを読み込んでください。
コンポーネントのファイル構成
標準的な Maven アーキタイプのレイアウト(Touch UI、最新の 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 Model
注:アンダースコア付きのディレクトリ(_cq_dialog)は、コロン付きの JCR ノード(cq:dialog)をファイルシステム上で表現したものです。FileVault のシリアライゼーションでは、この命名規則が必要です。
コンポーネントの定義(.content.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"/>
主なプロパティ
| プロパティ | 目的 |
|---|---|
jcr:title | コンポーネントブラウザーに表示する名前 |
jcr:description | コンポーネントブラウザーに表示するツールチップ |
componentGroup | コンポーネントブラウザーでのグループ分け。非表示にするには .hidden を使用 |
sling:resourceSuperType | 別のコンポーネントから継承(レンダリング、ダイアログ、編集設定) |
cq:isContainer | コンポーネントが子コンポーネントを含められる場合は true(parsys など) |
cq:icon | コンポーネントブラウザーに表示する Coral UI アイコン名 |
abbreviation | アイコンがない場合に使用する 2 文字の略称 |
エージェントのワークフロー:新しいコンポーネントの作成
ステップ 1:コンポーネントノードを定義する
jcr:primaryType="cq:Component"、タイトル、グループを指定して .content.xml を作成します。既存のコンポーネントを拡張する場合は、必要に応じて sling:resourceSuperType も指定します。
ステップ 2:Sling Model を作成する
Java モデルクラスを core/ モジュールに記述します。references/sling-models.md を参照してください。
@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; }
}
ステップ 3:HTL スクリプトを作成する
<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>
ステップ 4:ダイアログを作成する
Granite UI のフィールドについて詳しくは、references/dialogs.md を参照してください。
<?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>
ステップ 5:クライアントライブラリを追加する(必要な場合)
references/clientlibs.md を参照してください。
ステップ 6:編集動作を設定する(必要な場合)
<?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>
既存コンポーネントの拡張
sling:resourceSuperType を使用して、親からすべてを継承します。
<jcr:root ...
jcr:primaryType="cq:Component"
jcr:title="Custom Text"
sling:resourceSuperType="core/wcm/components/text/v2/text"
componentGroup="My Project"/>
自動的に継承されるもの:
- HTL レンダリングスクリプト(Sling リソースタイプの階層に従って解決)
- ダイアログ(Sling Resource Merger を使用して個別のフィールドをオーバーレイ可能)
- 編集設定、説明、アイコン
ダイアログのフィールドをオーバーレイするには、変更するノードだけを _cq_dialog/ の下に作成し、ダイアログのルートに sling:resourceSuperType を設定します。Sling Resource Merger が変更内容を親とマージします。
Core Components
一から構築するよりも、常に AEM Core Components の拡張を優先してください。次の機能が提供されます。
- 本番環境でテスト済みの、アクセシブルで SEO に配慮したマークアップ
- BEM CSS クラスの命名規則(
cmp-<name>__<element>--<modifier>) - JSON/SPA 用の Sling Model エクスポーター
- Style System のサポート
- Adobe Client Data Layer との統合
拡張対象としてよく使われる Core Components:
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
編集時のプレースホルダーパターン
コンポーネントは、空の場合でも編集モードで必ず何かを表示する必要があります。
<sly data-sly-use.template="core/wcm/components/commons/v1/templates.html"
data-sly-call="${template.placeholder @ isEmpty=!model.hasContent}"/>
または、手動のフォールバック:
<div class="cq-placeholder" data-emptytext="${component.properties.jcr:title}"
data-sly-test="${(wcmmode.edit || wcmmode.preview) && isEmpty}"></div>
コンテンツテンプレート(_cq_template/)
コンポーネントをページにドラッグしたときに、そのコンポーネントのコンテンツノードを事前に設定します。
<?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"/>
リソースタイプの解決
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の継承チェーンをたどります
重要なルール
- 必ず Touch UI(
cq:dialog)を使用してください。Classic UI のダイアログは非推奨です。 WCMUsePojoよりも Sling Models を優先してください。 Sling Models はテスト可能で、キャッシュ可能であり、AEM as a Cloud Service の標準です。/libsは変更しないでください。 必ず/appsにオーバーレイしてください。部分的なオーバーライドには Sling Resource Merger を使用してください。- コンポーネントにコンテンツがない場合は、必ず編集用プレースホルダーをレンダリングしてください。
- CSS クラスには BEM の命名規則を使用してください:
cmp-<component>__<element>--<modifier>。 componentGroupを設定してください。 設定しないと、オーサリング UI にコンポーネントが表示されません。- ダイアログのフィールド値を保存するには、
name属性に./プレフィックスを付けてください(例:name="./title")。これにより、コンポーネントのコンテンツノードを基準とした相対パスに書き込まれます。 - 一から構築する前に、必ず Core Components を拡張してください。
/apps配下のクライアントライブラリを/etc.clientlibs/経由で配信するには、allowProxy=trueが必要です。
リファレンスファイル
- references/dialogs.md — Touch UI ダイアログの構造、Granite UI フィールドの種類、タブ、検証
- references/clientlibs.md — クライアントライブラリフォルダーの設定、カテゴリ、依存関係、HTL への組み込み
- references/sling-models.md — Sling Model のアノテーション、インジェクション戦略、アダプター、テスト