コンポーネントは、AEM でエクスペリエンスを構築する際の中心です。コアコンポーネントと AEM プロジェクトアーキタイプを使うと、堅牢な既製のコンポーネントのツールセットを簡単に使い始めることができます。WKND チュートリアルでは、デベロッパーがこれらのツールの使用方法と、AEM サイトを作成するためのカスタムコンポーネントの作成方法を学びます。
このドキュメントを参照する前に、WKND チュートリアルを完了し、コアコンポーネントと AEM プロジェクトアーキタイプについてよく理解してください。
WKND チュートリアルでは、ほとんどの使用例をカバーしているので、このドキュメントはこれらのリソースを補完する目的でのみ提供されます。AEM でのコンポーネントの構造化および設定方法に関する詳細な技術的詳細を説明するものであり、入門用ガイドとしての意図されたものではありません。
この節では、独自コンポーネントの開発時に知っておくべき詳細の導入段階として、基本的な概念と注意点について説明します。
実際にコンポーネントの設定やコーディングを開始する前に、次の点について理解する必要があります。
全く新しいコンポーネントの作成に時間を費やす前に、既存のコンポーネントのカスタマイズや拡張を検討してください。コアコンポーネントは、柔軟で堅牢かつ十分にテストされた実稼働用コンポーネントのセットを提供します。
また、コアコンポーネントは、明確なカスタマイズパターンを備えており、独自のプロジェクトのニーズに合わせることもできます。
コンポーネントは、検索パスロジックに基づいたオーバーレイを使用して再定義することもできます。ただし、その場合 Sling Resource Merger が呼び出されないので、/apps
でオーバーレイ全体を定義する必要があります。
Sling Resource Merger を使用し、sling:resourceSuperType
プロパティを定義して、コンポーネントダイアログをオーバーライドすることもできます。
つまり、ダイアログ全体を再定義するのとは対照的に、再定義する必要があるのは相違点だけです。
コンポーネントは HTML を使用してレンダリングされます。コンポーネントは、必要なコンテンツを取得し、必要に応じてオーサー環境とパブリッシュ環境の両方でレンダリングするために必要なHTMLを定義する必要があります。
マークアップおよびレンダリングを行うコードと、コンポーネントのコンテンツ選択に関するロジックを制御するコードは、分離しておくことをお勧めします。
この方法をサポートするテンプレート言語が HTL です。HTL では、基盤となるビジネスロジックを定義するときにのみプログラミング言語を使用します。このメカニズムは、特定のビューに対して呼び出されるコードを強調表示し、必要に応じて、同じコンポーネントの異なるビューに対して特定のロジックを許可します。
この(オプション)ロジックは様々な方法で実装でき、特定のコマンドを使用して HTL から呼び出します。
AEM コンポーネントの構造は強力で柔軟性があります。以下は主な部分です。
構造の重要な構成要素となるのが、リソースタイプです。
このような抽象化をすることで、時間の経過と共にルックアンドフィールが変化しても、意図が変わることはありません。
コンポーネントの定義は次のように分解できます。
/libs/core/wcm/components
の下に配置されています。/apps/<myApp>/components
の下に配置されています。cq:Component
として定義され、次の主要な構成要素を持ちます。
cq:Component
定義によって定義されますが、一部はオプションの場合があります。<mycomponent> (cq:Component)
- コンポーネントの階層ノードjcr:title
- コンポーネントのタイトル。コンポーネントがコンポーネントブラウザーまたはコンポーネントコンソールリストされているときにラベルとして使用されますjcr:description
- コンポーネントの説明。コンポーネントブラウザーおよびコンポーネントコンソールでマウスオーバーヒントとして使用cq:editConfig (cq:EditConfig)
- コンポーネントの編集プロパティを定義し、コンポーネントをコンポーネントブラウザーに表示できるようにします
cq:childEditConfig (cq:EditConfig)
- 独自の cq:editConfig
を定義しない子コンポーネントの作成者 UI 要素を制御します。cq:dialog (nt:unstructured)
- このコンポーネントのダイアログ。ユーザーがコンポーネントを設定したり、コンテンツを編集したりできるインターフェイスを定義します。cq:design_dialog (nt:unstructured)
- このコンポーネントのデザイン編集コンポーネントのアイコンまたは省略形は、デベロッパーがコンポーネントを作成する際にコンポーネントの JCR プロパティで定義します。これらのプロパティは、次の順番で評価され、最初に見つかった有効なプロパティが使用されます。
cq:icon
- コンポーネントブラウザーで表示するための Coral UI ライブラリの標準的なアイコンを指定する String プロパティ
abbreviation
- コンポーネントブラウザーでのコンポーネント名の省略形をカスタマイズするための String プロパティ
jcr:title
プロパティの最初の 2 文字を使用して省略形が作成されます。
abbreviation_commentI18n
プロパティがある場合にのみ翻訳されます。これは、翻訳ヒントとして使用されます。cq:icon.png
または cq:icon.svg
- コンポーネントブラウザーに表示される、このコンポーネントのアイコン
.png
および .svg
ファイルのみがサポートされます。_cq_icon.png
や _cq_icon.svg
のように、ファイル名をエスケープする必要があります。.png
が .svg
よりも優先されますコンポーネントで上述のプロパティ(cq:icon
、abbreviation
、cq:icon.png
または cq:icon.svg
)が見つからない場合:
sling:resourceSuperType
プロパティに続くスーパーコンポーネント上の同じプロパティを検索します。jcr:title
プロパティの最初の文字から省略形を作成します。スーパーコンポーネントからアイコンの継承をキャンセルするために、コンポーネントで空の abbreviation
プロパティを設定すると、デフォルトの動作に戻ります。
コンポーネントコンソールには、特定のコンポーネントのアイコンの定義方法が表示されます。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "https://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="https://www.w3.org/2000/svg" xmlns:xlink="https://www.w3.org/1999/xlink" x="0px" y="0px"
width="20px" height="20px" viewBox="0 0 20 20" enable-background="new 0 0 20 20" xml:space="preserve">
<ellipse cx="5" cy="5" rx="3" ry="3" fill="#707070"/>
<ellipse cx="15" cy="5" rx="4" ry="4" fill="#707070"/>
<ellipse cx="5" cy="15" rx="5" ry="5" fill="#707070"/>
<ellipse cx="15" cy="15" rx="4" ry="4" fill="#707070"/>
</svg>
コンポーネントの定義に必要なノードまたはプロパティの多くは、両方の UI に共通です。コンポーネントがどちらの環境でも機能できるよう、相違点の独立性は確保されています。
コンポーネントはタイプ cq:Component
のノードで、次のプロパティと子ノードがあります。
名前 | 種類 | 説明 |
---|---|---|
. |
cq:Component |
これは現在のコンポーネントを表します。ノードタイプ cq:Component のコンポーネント。 |
componentGroup |
String |
これは、コンポーネントブラウザーでコンポーネントを選択できるグループを表します。「. 」で始まる値は、他のコンポーネントが継承する基本コンポーネントなど、UI から選択できないコンポーネントに使用されます。 |
cq:isContainer |
Boolean |
コンポーネントがコンテナコンポーネントかどうか、したがって段落システムなど他のコンポーネントを格納できるかどうかを示します。 |
cq:dialog |
nt:unstructured |
これは、コンポーネントの編集ダイアログの定義です。 |
cq:design_dialog |
nt:unstructured |
これは、コンポーネントのデザインダイアログの定義です。 |
cq:editConfig |
cq:EditConfig |
これはコンポーネントの編集構成を定義します。 |
cq:htmlTag |
nt:unstructured |
対象を囲んでいる HTML タグに追加されたその他のタグ属性を返します。自動生成された div に属性を追加できます。 |
cq:noDecoration |
Boolean |
true の場合、コンポーネントは、自動生成された div クラスと css クラスでレンダリングされません。 |
cq:template |
nt:unstructured |
このプロパティがある場合、コンポーネントがコンポーネントブラウザーから追加された際に、コンテンツテンプレートとしてこのノードを使用します。 |
jcr:created |
Date |
コンポーネントの作成日です。 |
jcr:description |
String |
コンポーネントの説明です。 |
jcr:title |
String |
コンポーネントのタイトルです。 |
sling:resourceSuperType |
String |
設定した場合、コンポーネントの継承元がこのコンポーネントになります。 |
component.html |
nt:file |
コンポーネントの HTL スクリプトファイルです。 |
cq:icon |
String |
この値は、🔗コンポーネントのアイコンを指し、コンポーネントブラウザーに表示されます。 |
を見ると、 テキスト コンポーネントには、次の要素のいくつかが表示されます。
特に重要なプロパティを次に示します。
jcr:title
- これは、コンポーネントブラウザ内のコンポーネントを識別するために使用されるコンポーネントのタイトルです。jcr:description
- コンポーネントの説明です。sling:resourceSuperType
- (定義のオーバーライドによる)コンポーネントの拡張時に、継承パスを示します。特に重要な子ノードを次に示します。
cq:editConfig
- 編集時のコンポーネントの視覚的な外観を制御します。cq:dialog
- このコンポーネントのコンテンツを編集するためのダイアログを定義します。cq:design_dialog
- このコンポーネントのデザイン編集オプションを指定します。ダイアログは、コンポーネントの主要な要素の 1 つです。作成者がコンテントページでコンポーネントを設定し、必要情報を提供するためのインターフェイスをダイアログが備えているからです。コンテンツ作成者がコンポーネントとやり取りする方法の詳細については、オーサリングドキュメントを参照してください。
コンポーネントの複雑さに応じて、ダイアログに 1 つ以上のタブが必要になる場合があります。
AEM コンポーネントのダイアログ:
nt:unstructured
の cq:dialog
ノードです。cq:Component
ノードの下のコンポーネント定義の横にあります。sling:resourceType
プロパティに基づいて、サーバーサイドで(Sling コンポーネントとして)レンダリングされます。nt:unstructured
プロパティを持つ sling:resourceType
ノードです。ダイアログ内で、個々のフィールドは次のように定義されます。
デザインダイアログは、コンテンツの編集と構成に使用されるダイアログに似ていますが、テンプレート作成者がページテンプレート上のそのコンポーネントのデザインの詳細をプロ構成および提供するためのインターフェイスを提供します。次に、コンテンツ作成者がページテンプレートを使用してコンテンツページを作成します。テンプレートの作成方法の詳細については、テンプレートドキュメントを参照してください。
ページテンプレートの編集時にはデザインダイアログが使用されます。ただし、すべてのコンポーネントで必要とされるわけではありません。例えば、タイトルと画像コンポーネントの両方にデザインのダイアログがありますが、ソーシャルメディア共有コンポーネントはありません。
AEM のルックアンドフィールは Coral UI と Granite UI で定義されています。
Granite UI で提供される幅広い基本ウィジェットは、オーサー環境でダイアログを作成するために使用されます。必要な場合には、選択したウィジェットを拡張し、独自のウィジェットを作成することができます。
以下のリソースについても参照してください。
コンポーネントダイアログで使用するウィジェットを作成するには、Granite UI フィールドコンポーネントを作成する必要があります。
ダイアログをフォーム要素の単純なコンテナと見なす場合、ダイアログコンテンツの主なコンテンツをフォームフィールドとして表示することもできます。新しいフォームフィールドを作成するには、リソースタイプを作成する必要があります。これは、コンポーネントの作成と同じです。 この作業を容易にするために、Granite UI は、sling:resourceSuperType
を使用して以下を継承する汎用フィールドコンポーネントを提供しています。
/libs/granite/ui/components/coral/foundation/form/field
より正確に言えば、Granite UI には、ダイアログ(より一般的に言えばフォーム)での使用に適した、幅広いフィールドコンポーネントが用意されています。
リソースタイプを作成したうえで、sling:resourceType
プロパティで作成したリソースタイプを参照して、新しいノードをダイアログに追加することによって、フィールドをインスタンス化できます。
レンダリング条件(rendercondition
)を使用して、ダイアログ内の特定のタブやフィールドへのアクセス権を持つユーザーを制御することもできます。以下に例を示します。
+ mybutton
- sling:resourceType = granite/ui/components/coral/foundation/button
+ rendercondition
- sling:resourceType = myapp/components/renderconditions/group
- groups = ["administrators"]
コンポーネントを作成したら、それを使用できるようにする必要があります。コンポーネントを使用すると、コンポーネントの構造とリポジトリの結果として得られるコンテンツの構造との関連がかわります。
コンポーネントを定義した上で、使用可能にする必要があります。コンポーネントをテンプレートで使用できるようにするには、テンプレートのレイアウトコンテナのポリシーでそのコンポーネントを有効にする必要があります。
テンプレートの作成方法の詳細については、テンプレートドキュメントを参照してください。
次のページにタイトルコンポーネントのインスタンスを作成して設定する場合:/content/wknd/language-masters/en/adventures/extreme-ironing.html
ここで、リポジトリー内に作成されたコンテンツの構造を確認できます。
特に、タイトルコンポーネントの実際のテキストに着目した場合:
jcr:title
プロパティが含まれており、このプロパティには作成者が入力したタイトルの実際のテキストが含まれています。sling:resourceType
参照も含まれます。定義されるプロパティは、個々の定義によって異なります。上記よりも複雑になる場合がありますが、同じ基本原則に従っています。
AEM 内のコンポーネントは、リソースタイプの階層の対象となります。プロパティでコンポーネントを拡張する場合に使用されます。sling:resourceSuperType
これにより、コンポーネントは別のコンポーネントから継承できます。
詳しくは、「コンポーネントの再利用」を参照してください。
この節では、コンポーネントの編集動作の設定方法について説明します。これには、コンポーネントに対して使用可能なアクションなどの属性、インプレースエディターの特性、コンポーネントに対するイベントに関連するリスナーも含まれます。
コンポーネントの編集動作を設定するには、タイプ cq:editConfig
の cq:EditConfig
ノードをコンポーネントノード(タイプ cq:Component
)の下に追加し、特定のプロパティと子ノードを追加します。使用可能なプロパティと子ノードを次に示します。
cq:editConfig
ノードのプロパティcq:editConfig
子ノード:
cq:dropTargets
(ノードタイプ nt:unstructured
):コンテンツファインダーのアセットからのドロップを受け入れることができるドロップターゲットのリストを定義します(1 つのドロップターゲットを許可します)cq:inplaceEditing
(ノードタイプ cq:InplaceEditingConfig
):コンポーネントのインプレース編集設定を定義しますcq:listeners
(ノードタイプ cq:EditListenersConfig
):コンポーネントでアクションを実行する前後の処理を定義しますAEM には、既存の設定が多数あります。CRXDE Lite のクエリツールを使用すると、特定のプロパティまたは子ノードを簡単に検索できます。
コンポーネントは、コンテンツがない場合でも必ず、作成者に表示される一部の HTML をレンダリングする必要があります。そうしないと、エディターのインターフェイスから視覚的に消えてしまい、技術的には存在しても、ページやエディターには表示されなくなります。この場合、作成者は空のコンポーネントを選択して操作することができません。
このため、ページがページエディターでレンダリングされる(WCM モードが edit
または preview
の場合)際に、コンポーネントは、表示された出力をレンダリングしない限り、プレースホルダーをレンダリングする必要があります。
プレースホルダーの一般的な HTML マークアップは次のとおりです。
<div class="cq-placeholder" data-emptytext="Component Name"></div>
上記のプレースホルダー HTML をレンダリングする一般的な HTL スクリプトは次のとおりです。
<div class="cq-placeholder" data-emptytext="${component.properties.jcr:title}"
data-sly-test="${(wcmmode.edit || wcmmode.preview) && isEmpty}"></div>
前の例では、isEmpty
は、コンポーネントにコンテンツがなくて作成者には見えない場合にのみ true になる変数です。
繰り返しを避けるために、アドビは、これらのプレースホルダーに、コアコンポーネントが提供するような HTL テンプレートを使用することをコンポーネントの実装者に推奨します。
その後、前のリンクでのテンプレートの使用は、次の HTL 行で行います。
<sly data-sly-use.template="core/wcm/components/commons/v1/templates.html"
data-sly-call="${template.placeholder @ isEmpty=!model.text}"></sly>
前の例では、model.text
はコンテンツが含まれていて表示されている場合にのみ true になる変数です。
このテンプレートの使用例は、コアコンポーネント(タイトルコンポーネントなど)で確認できます。
cq:dropTargets
ノード(ノードタイプ nt:unstructured
)では、コンテンツファインダーからドラッグしたアセットからのドロップを受け入れ可能なドロップターゲットを定義します。cq:DropTargetConfig
型のノードです。
タイプ cq:DropTargetConfig
の子ノードでは、コンポーネントのドロップターゲットを定義します。
インプレースエディターを使用すると、ダイアログを開くことなく、コンテンツフロー内で直接コンテンツを編集できます。例えば、標準のテキストとタイトルのコンポーネントには、どちらもインプレースエディターがあります。
インプレースエディターは、すべてのコンポーネントタイプで必要なものではありません。
cq:inplaceEditing
ノード(ノードタイプ cq:InplaceEditingConfig
)では、コンポーネントのインプレース編集設定を定義します。このノードは、次のプロパティを持つことができます。
プロパティ名 | プロパティタイプ | プロパティの値 |
---|---|---|
active |
Boolean |
true を使用して、コンポーネントのインプレース編集を有効にします。 |
configPath |
String |
エディター設定のパス(設定ノードで指定可能) |
editorType |
String |
次のタイプを使用できます。非 HTML のコンテンツ用の plaintext 、編集を開始する前にグラフィカルタイトルをプレーンテキストに変換する title 、リッチテキストエディターを使用する text |
次の設定では、コンポーネントのインプレース編集が可能になり、エディタータイプとして plaintext
が定義されます。
<cq:inplaceEditing
jcr:primaryType="cq:InplaceEditingConfig"
active="{Boolean}true"
editorType="plaintext"/>
ダイアログフィールドのイベントの処理は、カスタムクライアントライブラリのリスナーで行われます。
フィールドにロジックを挿入するには、以下を実行する必要があります。
これを実現するには、やり取りする、基になるウィジェットライブラリについて理解する必要があります。反応するイベントの識別については、Coral UI ドキュメントを参照してください
cq:listeners
ノード(ノードタイプ cq:EditListenersConfig
)では、コンポーネントでアクションを実行する前後の処理を定義します。次の表では、使用する可能性のあるプロパティ値の定義を示します。
プロパティ名 | プロパティの値 |
---|---|
beforedelete |
コンポーネントを削除する前にハンドラーがトリガーされます。 |
beforeedit |
コンポーネントを編集する前にハンドラーが呼び出されます。 |
beforecopy |
コンポーネントをコピーする前にハンドラーが呼び出されます。 |
beforeremove |
コンポーネントを移動する前にハンドラーが呼び出されます。 |
beforeinsert |
コンポーネントを挿入する前にハンドラーが呼び出されます。 |
beforechildinsert |
コンポーネントを別のコンポーネント(コンテナのみ)の内部に挿入する前にハンドラーが呼び出されます。 |
afterdelete |
コンポーネントを削除した後にハンドラーが呼び出されます。 |
afteredit |
コンポーネントを編集した後にハンドラーが呼び出されます。 |
aftercopy |
コンポーネントをコピーした後にハンドラーが呼び出されます。 |
afterinsert |
コンポーネントを挿入した後にハンドラーが呼び出されます。 |
aftermove |
コンポーネントを移動した後にハンドラーが呼び出されます。 |
afterchildinsert |
コンポーネントを別のコンポーネント(コンテナのみ)の内部に挿入した後にハンドラーが呼び出されます。 |
コンポーネントがネストされている場合は、cq:listeners
ノードでプロパティとして定義されるアクションに一定の制限があります。コンポーネントがネストされている場合、次のプロパティの値を にする必要があります REFRESH_PAGE
。
aftermove
aftercopy
イベントハンドラーを実装するときは、カスタム実装を組み込むことができます。次に例を示します(project.customerAction
は静的メソッドです)。
afteredit = "project.customerAction"
次の例は、REFRESH_INSERTED
設定と同等です。
afterinsert="function(path, definition) { this.refreshCreated(path, definition); }"
次の設定では、コンポーネントを削除、編集、挿入または移動した後にページが更新されます。
<cq:listeners
jcr:primaryType="cq:EditListenersConfig"
afterdelete="REFRESH_PAGE"
afteredit="REFRESH_PAGE"
afterinsert="REFRESH_PAGE"
afterMove="REFRESH_PAGE"/>
Granite UI および Granite UI ウィジェットでのフィールド検証は、foundation-validation
API を使用して実行します。詳しくは、foundation-valdiation
Granite のドキュメントを参照してください。
ダイアログが使用可能で準備が整ったときにのみ実行する必要があるカスタム JavaScript がある場合は、 dialog-ready
イベント。
このイベントは、ダイアログが読み込まれて(または再度読み込まれて)、使用の準備ができたときにトリガーされます。つまり、ダイアログの DOM に変更(作成/更新)がある場合に必ずトリガーされます。
dialog-ready
は、ダイアログ内のフィールドや類似のタスクをカスタマイズする JavaScript カスタムコードをフックするために使用できます。
プレビューモードに切り替えると、ページが更新されなくても WCM モード Cookie が設定されます。
レンダリングが WCM モードの影響を受けるコンポーネントの場合は、明確にそのコンポーネントを更新し、この Cookie の値を使用するように定義する必要があります。
デベロッパーは、以下をすばやく把握できるようにコンポーネントドキュメントに簡単にアクセスしたいと考えます。
このため、コンポーネント内で既存のドキュメントマークダウンを利用できるようにするのは非常に簡単です。
これには、コンポーネント構造に README.md
ファイルを配置するだけです。
その後、このマークダウンはコンポーネントコンソールに表示されるようになります。
サポートされているマークダウンは、コンテンツフラグメントの場合と同じです。