mcpField
A
aem-component-development

aem-component-development

github.com/headwirecom開発341 回インストール32 週間前に更新
リポジトリ

aem-component-development について

開発者やコーディングエージェント向けの Adobe Experience Manager コンポーネント開発スキルです。構成、実装手順、継承、編集時の指針を扱います。

主な機能

  1. 01コンポーネントのファイル構成と定義
  2. 02Sling Model と HTL の実装
  3. 03Touch UI ダイアログの指針
  4. 04Core Component の継承パターン
  5. 05編集プレースホルダーと編集動作

活用シーン

  1. 01AEM コンポーネントの新規作成
  2. 02既存 Core Component の拡張
  3. 03ダイアログと編集動作の設定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/headwirecom/aem-agent-skills --skill aem-component-development

インストール後、Claude Code で/aem-component-developmentを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
clientlibs.md
dialogs.md
sling-models.md

詳細

AEM コンポーネント開発

AEM コンポーネントは、ページコンテンツを構成する基本要素です。各コンポーネントは、次の要素をまとめる JCR 内の cq:Component ノードです。

  1. HTL マークアップ — レンダリングテンプレート(.html ファイル)
  2. Sling Model — サーバー側のビジネスロジック(Java)
  3. ダイアログ — コンテンツ編集用のオーサリング UI(cq:dialog)
  4. クライアントライブラリ — フロントエンドの動作に使用する CSS/JS
  5. 編集設定 — オーサリングツールバーの動作(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/text
  • core/wcm/components/image/v3/image
  • core/wcm/components/title/v3/title
  • core/wcm/components/teaser/v2/teaser
  • core/wcm/components/list/v4/list
  • core/wcm/components/container/v1/container
  • core/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 に基づいてコンポーネントを解決します。

  1. コンテンツノードに sling:resourceType = "myproject/components/hero" が設定されています
  2. Sling は /apps/myproject/components/hero/hero.html を探します
  3. 見つからない場合は、sling:resourceSuperType の継承チェーンを確認します
  4. /libs/ の検索パスにフォールバックします

リソースタイプ myproject/components/hero のスクリプト解決順序:

  1. hero.html(コンポーネント名に一致)
  2. html.html(拡張子に一致)
  3. GET.html(メソッドと拡張子に一致)
  4. 続いて、sling:resourceSuperType の継承チェーンをたどります

重要なルール

  1. 必ず Touch UI(cq:dialog)を使用してください。Classic UI のダイアログは非推奨です。
  2. WCMUsePojo よりも Sling Models を優先してください。 Sling Models はテスト可能で、キャッシュ可能であり、AEM as a Cloud Service の標準です。
  3. /libs は変更しないでください。 必ず /apps にオーバーレイしてください。部分的なオーバーライドには Sling Resource Merger を使用してください。
  4. コンポーネントにコンテンツがない場合は、必ず編集用プレースホルダーをレンダリングしてください。
  5. CSS クラスには BEM の命名規則を使用してください:cmp-<component>__<element>--<modifier>。
  6. componentGroup を設定してください。 設定しないと、オーサリング UI にコンポーネントが表示されません。
  7. ダイアログのフィールド値を保存するには、name 属性に ./ プレフィックスを付けてください(例:name="./title")。これにより、コンポーネントのコンテンツノードを基準とした相対パスに書き込まれます。
  8. 一から構築する前に、必ず Core Components を拡張してください。
  9. /apps 配下のクライアントライブラリを /etc.clientlibs/ 経由で配信するには、allowProxy=true が必要です。

リファレンスファイル

  • references/dialogs.md — Touch UI ダイアログの構造、Granite UI フィールドの種類、タブ、検証
  • references/clientlibs.md — クライアントライブラリフォルダーの設定、カテゴリ、依存関係、HTL への組み込み
  • references/sling-models.md — Sling Model のアノテーション、インジェクション戦略、アダプター、テスト

コメント