このチュートリアルでは、ダイアログで作成されたコンテンツを表示するカスタムAEM署名コンポーネントのエンドツーエンドの作成について説明し、Sling モデルの開発で、コンポーネントの HTL に入力するビジネスロジックをカプセル化します。
設定に必要なツールと手順を確認します。 ローカル開発環境.
前の章を正常に完了した場合は、プロジェクトを再利用し、スタータープロジェクトをチェックアウトする手順をスキップできます。
チュートリアルの構築元となるベースラインコードを確認します。
以下を確認します。 tutorial/custom-component-start
~から分岐する GitHub
$ cd aem-guides-wknd
$ git checkout tutorial/custom-component-start
Maven のスキルを使用して、ローカルのAEMインスタンスにコードベースをデプロイします。
$ mvn clean install -PautoInstallSinglePackage
AEM 6.5 または 6.4 を使用している場合、 classic
任意の Maven コマンドに対するプロファイル。
$ mvn clean install -PautoInstallSinglePackage -Pclassic
完成したコードは、 GitHub または、ブランチに切り替えて、コードをローカルでチェックアウトします。 tutorial/custom-component-solution
.
WKND チュートリアルのこの部分では、署名コンポーネントが作成され、記事の投稿者に関する作成済み情報を表示するのに使用されます。
署名コンポーネント
署名コンポーネントの実装には、署名コンテンツを収集するダイアログと、署名のを取得するカスタム Sling Model が含まれています。
最初に、署名コンポーネントノード構造を作成し、ダイアログを定義します。 これは、AEM のコンポーネントを表し、JCR 内のその場所によってコンポーネントのリソースタイプを暗黙的に定義します。
ダイアログは、コンテンツ作成者が提供できるインターフェイスを表示します。この実装の場合、AEM WCM コアコンポーネントの 画像 コンポーネントは、署名画像のオーサリングとレンダリングを処理するために利用されるので、コンポーネントの sling:resourceSuperType
.
内 ui.apps モジュール、に移動します。 /apps/wknd/components
をクリックし、 byline
.
の byline
フォルダを追加する新しいファイルの名前: .content.xml
次の項目に .content.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"
jcr:primaryType="cq:Component"
jcr:title="Byline"
jcr:description="Displays a contributor's byline."
componentGroup="WKND Sites Project - Content"
sling:resourceSuperType="core/wcm/components/image/v2/image"/>
上記の XML ファイルは、タイトル、説明、グループなど、コンポーネントの定義を提供します。 この sling:resourceSuperType
ポイント core/wcm/components/image/v2/image
( これは コア画像コンポーネント.
の byline
フォルダー、新しいファイルを追加 byline.html
:コンポーネントのHTML表示を担当します。 ファイルにフォルダーと同じ名前を付けることは重要です。これは、Sling がこのリソースタイプをレンダリングする際に使用するデフォルトのスクリプトになるからです。
以下のコードを byline.html
に追加します。
<!--/* byline.html */-->
<div data-sly-use.placeholderTemplate="core/wcm/components/commons/v1/templates.html">
</div>
<sly data-sly-call="${placeholderTemplate.placeholder @ isEmpty=true}"></sly>
byline.html
が 後で再び行うSling モデルが作成されたら、 HTL ファイルの現在の状態を使用すると、コンポーネントをページにドラッグ&ドロップしたときに、AEM Sites のページエディターで空の状態で表示できます。
次に、以下のフィールドを含む、署名コンポーネント用のダイアログを定義します。
の byline
フォルダー、新しいフォルダーを作成します。 _cq_dialog
.
の下 byline/_cq_dialog
という名前の新しいファイルを追加します。 .content.xml
. これは、ダイアログの XML 定義です。 次の 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="Byline"
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}false">
<items jcr:primaryType="nt:unstructured">
<asset
jcr:primaryType="nt:unstructured"
sling:hideResource="{Boolean}false"/>
<metadata
jcr:primaryType="nt:unstructured"
sling:hideResource="{Boolean}true"/>
<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">
<name
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
emptyText="Enter the contributor's name to display."
fieldDescription="The contributor's name to display."
fieldLabel="Name"
name="./name"
required="{Boolean}true"/>
<occupations
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/multifield"
fieldDescription="A list of the contributor's occupations."
fieldLabel="Occupations"
required="{Boolean}false">
<field
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
emptyText="Enter an occupation"
name="./occupations"/>
</occupations>
</items>
</column>
</items>
</columns>
</items>
</properties>
</items>
</tabs>
</items>
</content>
</jcr:root>
これらのダイアログノード定義では、 Sling Resource Merger どのダイアログタブが sling:resourceSuperType
コンポーネント(この場合は) コアコンポーネントの画像コンポーネント.
ダイアログ作成と同じ方法でポリシーダイアログ(以前のデザインダイアログ)を作成して、コアコンポーネントの画像コンポーネントから継承されたポリシー設定の不要なフィールドを非表示にします。
の byline
フォルダー、新しいフォルダーを作成します。 _cq_design_dialog
.
の下 byline/_cq_design_dialog
という名前の新しいファイルを作成します。 .content.xml
. ファイルを次のように更新します。を次の XML に置き換えます。 を開くのが最も簡単です。 .content.xml
をクリックし、その中に以下の XML をコピー&ペーストします。
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/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="Byline"
sling:resourceType="cq/gui/components/authoring/dialog">
<content
jcr:primaryType="nt:unstructured">
<items jcr:primaryType="nt:unstructured">
<tabs
jcr:primaryType="nt:unstructured">
<items jcr:primaryType="nt:unstructured">
<properties
jcr:primaryType="nt:unstructured">
<items jcr:primaryType="nt:unstructured">
<content
jcr:primaryType="nt:unstructured">
<items jcr:primaryType="nt:unstructured">
<decorative
jcr:primaryType="nt:unstructured"
sling:hideResource="{Boolean}true"/>
<altValueFromDAM
jcr:primaryType="nt:unstructured"
sling:hideResource="{Boolean}true"/>
<titleValueFromDAM
jcr:primaryType="nt:unstructured"
sling:hideResource="{Boolean}true"/>
<displayCaptionPopup
jcr:primaryType="nt:unstructured"
sling:hideResource="{Boolean}true"/>
<disableUuidTracking
jcr:primaryType="nt:unstructured"
sling:hideResource="{Boolean}true"/>
</items>
</content>
</items>
</properties>
<features
jcr:primaryType="nt:unstructured">
<items jcr:primaryType="nt:unstructured">
<content
jcr:primaryType="nt:unstructured">
<items jcr:primaryType="nt:unstructured">
<accordion
jcr:primaryType="nt:unstructured">
<items jcr:primaryType="nt:unstructured">
<orientation
jcr:primaryType="nt:unstructured"
sling:hideResource="{Boolean}true"/>
<crop
jcr:primaryType="nt:unstructured"
sling:hideResource="{Boolean}true"/>
</items>
</accordion>
</items>
</content>
</items>
</features>
</items>
</tabs>
</items>
</content>
</jcr:root>
前の基準 ポリシーダイアログ XML は コアコンポーネントの画像コンポーネント.
ダイアログ設定のと同様に、 Sling Resource Merger を使用して、無関係なフィールドを非表示にします。これ以外の場合は、 sling:resourceSuperType
を使用して、 sling:hideResource="{Boolean}true"
プロパティ。
変更を同期 ui.apps
IDE または Maven スキルを使用して、
AEMコンポーネントの開発に重点を置いたシンプルな作業を維持するために、署名コンポーネントを現在の状態で記事ページに追加し、 cq:Component
ノード定義がデプロイされ、正しく設定されている場合、AEMは新しいコンポーネント定義を認識し、コンポーネントのダイアログがオーサリングに機能します。
まず、サンプルのヘッドショットをAEM Assetsにアップロードして、署名コンポーネントに画像を設定する際に使用します。
AEM Assetsの LA Skateparks フォルダーに移動します。 http://localhost:4502/assets.html/content/dam/wknd/en/magazine/la-skateparks.
のヘッドショットをアップロード stacey-roswells.jpg をフォルダーに追加します。
次に、署名コンポーネントをAEMのページに追加します。 署名コンポーネントを WKND Sites プロジェクト — コンテンツ コンポーネントグループ(経由) ui.apps/src/main/content/jcr_root/apps/wknd/components/byline/.content.xml
定義を使用する場合、任意のユーザーが自動的に使用できます コンテナ その ポリシー 許可 WKND Sites プロジェクト — コンテンツ コンポーネントグループに割り当てられます。このグループには、記事ページのレイアウトコンテナが含まれます。
LA Skatepark の記事 ( ) に移動します。 http://localhost:4502/editor.html/content/wknd/us/en/magazine/guide-la-skateparks.html
左側のサイドバーから、 署名コンポーネント 次に bottom をクリックします。
左側のサイドバーが開いて表示されたことと、アセットファインダーが選択されていることを確認します。
を選択します。 署名コンポーネントのプレースホルダーをクリックし、次にアクションバーを表示して、 レンチ アイコンをクリックしてダイアログを開きます。
ダイアログが開き、最初のタブ(アセット)がアクティブな状態で、左側のサイドバーを開き、アセットファインダーから画像を画像ドロップゾーンにドラッグします。 WKND ui.content パッケージに含まれる Stacey Roswells のバイオ画像を検索するには、「stacey」を検索します。
画像を追加したら、「プロパティ」タブをクリックして「名前」および「職業」に入力します。
職業を入力する場合は、次の場所に入力します。 逆アルファベット Sling Model で実装する英文化化ビジネスロジックが見やすいように、順序を指定します。
次をタップします。 完了 ボタンをクリックして変更を保存します。
AEM作成者は、ダイアログを使用してコンポーネントを設定および作成します。 署名コンポーネントの開発のこの時点では、データの収集用のダイアログが含まれますが、作成したコンテンツをレンダリングするロジックはまだ追加されていません。 したがって、プレースホルダーのみが表示されます。
ダイアログを保存したら、に移動します。 CRXDE Lite およびは、コンポーネントのコンテンツがAEMページの署名コンポーネントコンテンツノードに格納される方法を確認します。
LA Skate Parks ページの下に、署名コンポーネントのコンテンツノードを見つけます。 /content/wknd/us/en/magazine/guide-la-skateparks/jcr:content/root/container/container/byline
.
プロパティ名に注意してください name
, occupations
、および fileReference
が 署名ノード.
また、 sling:resourceType
の wknd/components/content/byline
これは、このコンテンツノードを署名コンポーネントの実装にバインドするものです。
次に、データモデルとして機能し、署名コンポーネントのビジネスロジックを格納する Sling Model を作成します。
Sling モデルは、JCR から Java 変数へのデータのマッピングを容易にし、AEMのコンテキストで開発する際に他の多くの点を提供する注釈駆動型の Java「POJO」(Plain Old Java Objects) です。
署名 Sling モデルは、AEMが提供する複数の Java API に依存します。 これらの API は、 dependencies
次に示す core
モジュールの POM ファイル。 このチュートリアルに使用するプロジェクトは、AEM as a Cloud Service用に構築されています。 ただし、AEM 6.5/6.4 との下位互換性がある点は一意です。そのため、Cloud ServiceとAEM 6.x の両方の依存関係が含まれます。
を開きます。 pom.xml
の下のファイル <src>/aem-guides-wknd/core/pom.xml
.
依存関係を検索 aem-sdk-api
- AEMas a Cloud Serviceのみ
<dependency>
<groupId>com.adobe.aem</groupId>
<artifactId>aem-sdk-api</artifactId>
</dependency>
この aem-sdk-api には、AEMで公開されるすべてのパブリック Java API が含まれています。 この aem-sdk-api
は、このプロジェクトを構築する際にデフォルトで使用されます。 バージョンは、次の場所にあるプロジェクトのルートにある親リアクター POM に保持されます。 aem-guides-wknd/pom.xml
.
の依存関係を検索 uber-jar
- AEM 6.5/6.4 のみ
...
<dependency>
<groupId>com.adobe.aem</groupId>
<artifactId>uber-jar</artifactId>
<classifier>apis</classifier>
</dependency>
...
この uber-jar
が含まれるのは、 classic
プロファイルが呼び出されました。 mvn clean install -PautoInstallSinglePackage -Pclassic
. これもこのプロジェクトに固有のものです。 AEMプロジェクトアーキタイプから生成される、実際のプロジェクトでは、 uber-jar
指定したAEMのバージョンが 6.5 または 6.4 の場合、がデフォルトになります。
この uber-jar には、AEM 6.x で公開されているすべてのパブリック Java API が含まれています。バージョンは、プロジェクトのルートにある親リアクター POM に保持されます aem-guides-wknd/pom.xml
.
依存関係を検索 core.wcm.components.core
:
<!-- Core Component Dependency -->
<dependency>
<groupId>com.adobe.cq</groupId>
<artifactId>core.wcm.components.core</artifactId>
</dependency>
これは、AEMコアコンポーネントによって公開されるすべてのパブリック Java API です。 AEMコアコンポーネントは、AEMの外部で管理されるプロジェクトなので、別のリリースサイクルがあります。 このため、依存関係は別々に含める必要があり、 not 次に含まれる uber-jar
または aem-sdk-api
.
uber-jar と同様に、この依存関係のバージョンは、次の場所にある親リアクター pom ファイルに保持されます。 aem-guides-wknd/pom.xml
.
このチュートリアルの後半では、コアコンポーネントの画像クラスを使用して、署名コンポーネントに画像を表示します。 Sling モデルを構築してコンパイルするには、コアコンポーネントの依存関係が必要です。
署名用のパブリック Java インターフェイスを作成します。 Byline.java
は、 byline.html
HTL スクリプト。
内 aem-guides-wknd.core
下のモジュール core/src/main/java/com/adobe/aem/guides/wknd/core/models
という名前の新しいファイルを作成します。 Byline.java
以下のメソッドで Byline.java
を更新します。
package com.adobe.aem.guides.wknd.core.models;
import java.util.List;
/**
* Represents the Byline AEM Component for the WKND Site project.
**/
public interface Byline {
/***
* @return a string to display as the name.
*/
String getName();
/***
* Occupations are to be sorted alphabetically in a descending order.
*
* @return a list of occupations.
*/
List<String> getOccupations();
/***
* @return a boolean if the component has enough content to display.
*/
boolean isEmpty();
}
最初の 2 つのメソッドは、 名前 および 職業 署名コンポーネント用の
この isEmpty()
メソッドは、コンポーネントにレンダリングするコンテンツがあるかどうか、または設定を待っているかどうかを判断するために使用されます。
画像に対するメソッドがないことに注意してください。 その理由を後で見てみましょう.
パブリック Java クラス(この場合は Sling モデル)を含む Java パッケージは、パッケージの package-info.java
ファイル。
WKND ソースの Java パッケージ以降 com.adobe.aem.guides.wknd.core.models
を宣言すると、のバージョンが 1.0.0
を追加し、新しい公開インターフェイスおよびメソッドを追加する場合は、バージョンを 1.1.0
. 次の場所にあるファイルを開きます。 core/src/main/java/com/adobe/aem/guides/wknd/core/models/package-info.java
および更新 @Version("1.0.0")
から @Version("1.1.0")
.
"'
@Version("2.1.0")
package com.adobe.aem.guides.wknd.core.models;
import org.osgi.annotation.versioning.Version;
"'
このパッケージ内のファイルに変更が加えられると、 パッケージのバージョンは、意味的に調整する必要があります. そうでない場合、Maven プロジェクトの bnd-baseline-maven-plugin は無効なパッケージバージョンを検出し、ビルドを中断します。 幸運なことに、Maven プラグインが失敗すると、無効な Java パッケージのバージョンと、そのバージョンが表示されるはずです。 更新されたばかりの @Version("...")
Java パッケージの宣言 package-info.java
を、プラグインで推奨される修正用のバージョンに追加する。
BylineImpl.java
は、 Byline.java
以前に定義されたインターフェイス。 BylineImpl.java
の完全なコードは、この節の最後に記載しています。
という名前の新しいフォルダーを作成します。 impl
下 core/src/main/java/com/adobe/aem/guides/core/models
.
内 impl
フォルダー新規ファイルを作成 BylineImpl.java
.
次を開きます: BylineImpl.java
. これによって Byline
インターフェイス。 IDE のオートコンプリート機能を使用するか、手動でファイルを更新して、 Byline
インターフェイス:
package com.adobe.aem.guides.wknd.core.models.impl;
import java.util.List;
import com.adobe.aem.guides.wknd.core.models.Byline;
public class BylineImpl implements Byline {
@Override
public String getName() {
// TODO Auto-generated method stub
return null;
}
@Override
public List<String> getOccupations() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isEmpty() {
// TODO Auto-generated method stub
return false;
}
}
以下のクラスレベルの注釈で BylineImpl.java
を更新して、Sling Model 注釈を追加します。この @Model(..)
注釈は、クラスを Sling モデルに変換するものです。
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
...
@Model(
adaptables = {SlingHttpServletRequest.class},
adapters = {Byline.class},
resourceType = {BylineImpl.RESOURCE_TYPE},
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)
public class BylineImpl implements Byline {
protected static final String RESOURCE_TYPE = "wknd/components/byline";
...
}
この注釈とそのパラメーターを確認してみましょう:
@Model
annotation は、BylineImpl をAEMにデプロイする際に Sling Model として登録します。adaptables
パラメーターは、このモデルがリクエストで適応できることを指定します。adapters
パラメーターを使用すると、実装クラスを Byline インターフェイスに登録できます。 これにより、HTL スクリプトは(impl ではなく)インターフェイスを介して Sling Model を呼び出すことができます。 adapters について詳しくは、こちらを参照してください。resourceType
は署名コンポーネントのリソースタイプ(以前に作成した)を指し、複数の実装がある場合に正しいモデルの解決に役立ちます。 モデルクラスのリソースタイプとの関連付けについて詳しくは、こちらを参照してください。最初に取り組む方法は getName()
これは、プロパティの下の署名の JCR コンテンツノードに保存された値を返します。 name
.
この場合、 @ValueMapValue
Sling Model 注釈は、リクエストのリソースの ValueMap を使用して Java フィールドに値を挿入するために使用されます。
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
public class BylineImpl implements Byline {
...
@ValueMapValue
private String name;
...
@Override
public String getName() {
return name;
}
...
}
JCR プロパティは Java フィールドと同じ名前(両方とも「name」)を持つので、 @ValueMapValue
はこの関連付けを自動的に解決し、プロパティの値を Java フィールドに挿入します。
次に実装する方法は次のとおりです。 getOccupations()
. このメソッドは、JCR プロパティに保存されているすべての職業を収集します occupations
並べ替えられた(アルファベット順の)コレクションを返します。
に示したのと同じ方法の使用 getName()
プロパティ値は、Sling モデルのフィールドに挿入できます。
挿入された Java フィールドを介して JCR プロパティ値を Sling モデルで使用できるようになったら、 occupations
を指定しない場合、並べ替えビジネスロジックは getOccupations()
メソッド。
import java.util.ArrayList;
import java.util.Collections;
...
public class BylineImpl implements Byline {
...
@ValueMapValue
private List<String> occupations;
...
@Override
public List<String> getOccupations() {
if (occupations != null) {
Collections.sort(occupations);
return new ArrayList<String>(occupations);
} else {
return Collections.emptyList();
}
}
...
}
...
最後のパブリックメソッドは、 isEmpty()
これにより、コンポーネントがレンダリングに十分な作成を行ったと見なすタイミングが決まります。
このコンポーネントには、名前、画像および職業の 3 つのフィールドをすべて入力する必要があるというビジネス要件があります 前 コンポーネントはレンダリングできます。
import org.apache.commons.lang3.StringUtils;
...
public class BylineImpl implements Byline {
...
@Override
public boolean isEmpty() {
if (StringUtils.isBlank(name)) {
// Name is missing, but required
return true;
} else if (occupations == null || occupations.isEmpty()) {
// At least one occupation is required
return true;
} else if (/* image is not null, logic to be determined */) {
// A valid image is required
return true;
} else {
// Everything is populated, so this component is not considered empty
return false;
}
}
...
}
名前と職業の条件を確認することは簡単です ( そして Apache Commons Lang3 は常に便利です StringUtils (クラス)が、 画像の存在 は、コアコンポーネントの画像コンポーネントを画像の表示に使用するので、検証できます。
これに対処するには、2 つの方法があります。
をチェックします。 fileReference
JCR プロパティがアセットに解決されます。 または このリソースをコアコンポーネントの画像 Sling モデルに変換し、 getSrc()
メソッドが空ではありません。
次を選択します。 秒 アプローチ。 第 1 のアプローチで十分である可能性が高いですが、このチュートリアルでは、Sling モデルの他の機能を調べるために後者を使用します。
画像を取得するプライベートメソッドを作成します。 このメソッドをプライベートにしておくのは、HTL 自体の画像オブジェクトを公開する必要がなく、isEmpty().
() を実行するためにのみ使用するからです。
次のプライベートメソッドを getImage()
:
import com.adobe.cq.wcm.core.components.models.Image;
...
private Image getImage() {
Image image = null;
// Figure out how to populate the image variable!
return image;
}
上記のように、 Image Sling Model:
1 つ目は、 @Self
注釈 ( 現在のリクエストをコアコンポーネントの Image.class
2 つ目は、 Apache Sling ModelFactory OSGi サービスは非常に便利なサービスで、Java コードで他のタイプの Sling モデルを作成するのに役立ちます。
第 2 のアプローチを選択します。
実際の実装では、次を使用して「1」にアプローチします。 @Self
よりシンプルでエレガントなソリューションなので、をお勧めします。 このチュートリアルでは、2 つ目の方法を使用します。非常に役立つ Sling モデルのより多くのファセットを調査する必要があるので、2 つ目の方法を使用します。より複雑なコンポーネントです。
Sling モデルは OSGi サービスではなく Java POJO なので、通常の OSGi 挿入注釈です @Reference
できません を使用する代わりに、Sling Model は特別な @OSGiService 類似の機能を提供する注釈。
更新 BylineImpl.java
を含めるには OSGiService
挿入する注釈 ModelFactory
:
import org.apache.sling.models.factory.ModelFactory;
import org.apache.sling.models.annotations.injectorspecific.OSGiService;
...
public class BylineImpl implements Byline {
...
@OSGiService
private ModelFactory modelFactory;
}
を使用 ModelFactory
使用可能なコアコンポーネントの画像 Sling モデルは、次のものを使用して作成できます。
modelFactory.getModelFromWrappedRequest(SlingHttpServletRequest request, Resource resource, java.lang.Class<T> targetClass)
ただし、このメソッドにはリクエストとリソースの両方が必要で、Sling モデルではまだ使用できません。 これらを取得するには、より多くの Sling Model 注釈が使用されます。
現在のリクエストを取得するには、 @Self 注釈を使用して、 adaptable
( @Model(..)
as SlingHttpServletRequest.class
を Java クラスフィールドに追加します。
を @Self 注釈を使用して SlingHttpServletRequest リクエスト:
import org.apache.sling.models.annotations.injectorspecific.Self;
...
@Self
private SlingHttpServletRequest request;
注意:を使用 @Self Image image
コアコンポーネントの画像 Sling モデルを挿入することは、上記のオプションでした。 @Self
annotation は、適応可能なオブジェクト(この例では SlingHttpServletRequest)の挿入を試み、注釈フィールドタイプに合わせます。 コアコンポーネントの画像 Sling Model は SlingHttpServletRequest オブジェクトから適応可能なので、これなら機能したはずです。また、説明的な 2 番目の方法よりも少ないコードで済みます。
これで、ModelFactory API で画像モデルをインスタンス化するために必要な変数を挿入できました。次に、Sling Model の @PostConstruct 注釈を使用して、Sling Model をインスタンス化した後、このオブジェクトを取得します。
@PostConstruct
は非常に役に立ち、コンストラクターと同様の能力で動作しますが、クラスがインスタンス化され、注釈が付けられたすべての Java フィールドが挿入された後に呼び出されます。 他の Sling モデルの注釈は Java クラスフィールド(変数)に注釈を付けます。 @PostConstruct
は、通常、 init()
(ただし、任意の名前を付けることができます)。
追加 @PostConstruct メソッド:
import javax.annotation.PostConstruct;
...
public class BylineImpl implements Byline {
...
private Image image;
@PostConstruct
private void init() {
image = modelFactory.getModelFromWrappedRequest(request,
request.getResource(),
Image.class);
}
...
}
Sling Model は OSGi サービスではないので、クラスの状態を安全に管理できます。頻繁 @PostConstruct
プレーンコンストラクターと同様に、後で使用するために Sling Model クラスの状態を派生および設定します。
なお、 @PostConstruct
メソッドで例外がスローされ、Sling モデルはインスタンス化されません(null になります)。
getImage() を更新して、画像オブジェクトを返すだけで済むようになりました。
/**
* @return the Image Sling Model of this resource, or null if the resource cannot create a valid Image Sling Model.
*/
private Image getImage() {
return image;
}
次に戻ろう isEmpty()
実装を完了します。
@Override
public boolean isEmpty() {
final Image componentImage = getImage();
if (StringUtils.isBlank(name)) {
// Name is missing, but required
return true;
} else if (occupations == null || occupations.isEmpty()) {
// At least one occupation is required
return true;
} else if (componentImage == null || StringUtils.isBlank(componentImage.getSrc())) {
// A valid image is required
return true;
} else {
// Everything is populated, so this component is not considered empty
return false;
}
}
複数の getImage()
は初期化されたを返すので、問題ありません image
クラス変数で、を呼び出さない modelFactory.getModelFromWrappedRequest(...)
それは過度に費用がかかるわけではなく、不必要に呼び出すのを避ける価値がある。
最終 BylineImpl.java
は次のようになります。
package com.adobe.aem.guides.wknd.core.models.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.PostConstruct;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.OSGiService;
import org.apache.sling.models.annotations.injectorspecific.Self;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
import org.apache.sling.models.factory.ModelFactory;
import com.adobe.aem.guides.wknd.core.models.Byline;
import com.adobe.cq.wcm.core.components.models.Image;
@Model(
adaptables = {SlingHttpServletRequest.class},
adapters = {Byline.class},
resourceType = {BylineImpl.RESOURCE_TYPE},
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)
public class BylineImpl implements Byline {
protected static final String RESOURCE_TYPE = "wknd/components/byline";
@Self
private SlingHttpServletRequest request;
@OSGiService
private ModelFactory modelFactory;
@ValueMapValue
private String name;
@ValueMapValue
private List<String> occupations;
private Image image;
/**
* @PostConstruct is immediately called after the class has been initialized
* but BEFORE any of the other public methods.
* It is a good method to initialize variables that will be used by methods in the rest of the model
*
*/
@PostConstruct
private void init() {
// set the image object
image = modelFactory.getModelFromWrappedRequest(request, request.getResource(), Image.class);
}
@Override
public String getName() {
return name;
}
@Override
public List<String> getOccupations() {
if (occupations != null) {
Collections.sort(occupations);
return new ArrayList<String>(occupations);
} else {
return Collections.emptyList();
}
}
@Override
public boolean isEmpty() {
final Image componentImage = getImage();
if (StringUtils.isBlank(name)) {
// Name is missing, but required
return true;
} else if (occupations == null || occupations.isEmpty()) {
// At least one occupation is required
return true;
} else if (componentImage == null || StringUtils.isBlank(componentImage.getSrc())) {
// A valid image is required
return true;
} else {
// Everything is populated, so this component is not considered empty
return false;
}
}
/**
* @return the Image Sling Model of this resource, or null if the resource cannot create a valid Image Sling Model.
*/
private Image getImage() {
return image;
}
}
内 ui.apps
モジュール、開く /apps/wknd/components/byline/byline.html
以前のAEMコンポーネントの設定で作成しました。
<div data-sly-use.placeholderTemplate="core/wcm/components/commons/v1/templates.html">
</div>
<sly data-sly-call="${placeholderTemplate.placeholder @ isEmpty=false}"></sly>
この HTL スクリプトでおこなうことを確認しましょう。
この placeholderTemplate
は、コアコンポーネントのプレースホルダーを指しています。このプレースホルダーは、コンポーネントが完全に設定されていない場合に表示されます。 これは、AEM Sitesページエディターで、上で説明したように、コンポーネントタイトルを持つボックスとしてレンダリングされます ( cq:Component
's jcr:title
プロパティ。
この data-sly-call="${placeholderTemplate.placeholder @ isEmpty=false}
は、 placeholderTemplate
上で定義され、ブール値で渡されます ( 現在、次のようにハードコードされています: false
) をプレースホルダーテンプレートに追加します。 条件 isEmpty
が true の場合、プレースホルダテンプレートはグレーのボックスをレンダリングし、そうでない場合は何もレンダリングされません。
以下のスケルタル HTML 構造で byline.html を更新します。
<div data-sly-use.placeholderTemplate="core/wcm/components/commons/v1/templates.html"
class="cmp-byline">
<div class="cmp-byline__image">
<!--/* Include the Core Components Image Component */-->
</div>
<h2 class="cmp-byline__name"><!--/* Include the name */--></h2>
<p class="cmp-byline__occupations"><!--/* Include the occupations */--></p>
</div>
<sly data-sly-call="${placeholderTemplate.placeholder @ isEmpty=true}"></sly>
CSS クラスは BEM 命名規則に従うことに注意してください。BEM 規則の使用は必須ではありませんが、コアコンポーネント CSS クラスで使用され、一般的にクリーンで読みやすい CSS ルールになるので、BEM をお勧めします。
この ブロックステートメントを使用 は、Sling モデルオブジェクトを HTL スクリプトでインスタンス化し、HTL 変数に割り当てるために使用されます。
data-sly-use.byline="com.adobe.aem.guides.wknd.models.Byline"
は、BylineImpl で実装された署名インターフェイス (com.adobe.aem.guides.wknd.models.Byline) を使用して、現在の SlingHttpServletRequest をそのインターフェイスに適応し、結果を HTL 変数名のバイライン ( data-sly-use.<variable-name>
) をクリックします。
外部を更新 div
を参照する 署名 Sling Model by its public interface:
<div data-sly-use.byline="com.adobe.aem.guides.wknd.core.models.Byline"
data-sly-use.placeholderTemplate="core/wcm/components/commons/v1/templates.html"
class="cmp-byline">
...
</div>
HTL は、 JSTL およびは、Java ゲッターメソッド名と同じ短縮形を使用します。
例えば、署名 Sling モデルのの呼び出し getName()
方法はに短縮できます byline.name
同様に、 byline.isEmpty
の場合は、 byline.empty
. 完全なメソッド名の使用 byline.getName
または byline.isEmpty
でも動作します。 次の点に注意してください。 ()
は、HTL でメソッドを呼び出すためには使用されません(JSTL と同様)。
パラメーターが必要な Java メソッド できません を HTL で使用する。 これは、HTL のロジックをシンプルにするための設計によるものです。
署名名は、 getName()
メソッドを使用します。 ${byline.name}
.
を更新します。 h2
タグ:
<h2 class="cmp-byline__name">${byline.name}</h2>
HTL 式のオプション HTL 内のコンテンツの修飾子として機能し、日付の書式設定から i18n 翻訳まで幅広く機能します。 また、式は、リストの結合や値の配列に使用でき、職業をコンマ区切り形式で表示するのに必要です。
式は @
演算子を使用して、HTL 式に含めることができます。
職業のリストを「,」で結合するには、以下のコードを使用します。
<p class="cmp-byline__occupations">${byline.occupations @ join=', '}</p>
AEMコンポーネントのほとんどの HTL スクリプトでは、 プレースホルダーパラダイム 作成者に視覚的な手がかりを提供する コンポーネントが誤って作成され、AEM パブリッシュに表示されないことを示す. この判断を推進するには、コンポーネントの背後の Sling Model のメソッド(この場合 Byline.isEmpty()
())を実装する必要があります。
isEmpty()
署名 Sling Model でが呼び出され、結果(またはその負の値)が !
演算子 ) が hasContent
:
外部を更新 div
という名前の HTL 変数を保存するには、次のようにします。 hasContent
:
<div data-sly-use.byline="com.adobe.aem.guides.wknd.core.models.Byline"
data-sly-use.placeholderTemplate="core/wcm/components/commons/v1/templates.html"
data-sly-test.hasContent="${!byline.empty}"
class="cmp-byline">
...
</div>
の使用に注意してください。 data-sly-test
、HTL test
ブロックは、HTL 変数を設定し、HTL 式の結果が真かどうかに基づいて、その変数が基にするHTML要素をレンダリング/レンダリングしないので、興味深いものです。 「真」の場合、HTML要素はレンダリングされ、そうでない場合、レンダリングされません。
この HTL 変数 hasContent
を再利用して、プレースホルダーを条件付きで表示/非表示にできるようになりました。
条件付き呼び出しを placeholderTemplate
を次のように指定します。
<sly data-sly-call="${placeholderTemplate.placeholder @ isEmpty=!hasContent}"></sly>
の HTL スクリプト byline.html
がほぼ完了し、画像しか欠落していなくなりました。
コアコンポーネントの画像コンポーネント sling:resourceSuperType
を使用して画像のオーサリングを提供しているので、コアコンポーネントの画像コンポーネントを使用して画像をレンダリングすることもできます。
この場合、現在の署名リソースを含める必要がありますが、リソースタイプ core/wcm/components/image/v2/image
. これは、コンポーネントを再利用する際の強力なパターンです。 これに対して、HTL の data-sly-resource
ブロックが使用されます。
を div
クラスを持つ cmp-byline__image
を次のように設定します。
<div class="cmp-byline__image"
data-sly-resource="${ '.' @ resourceType = 'core/wcm/components/image/v2/image' }"></div>
この data-sly-resource
(相対パスを使用して現在のリソースを含む) '.'
現在のリソース(または署名コンテンツリソース)を、 core/wcm/components/image/v2/image
.
コアコンポーネントのリソースタイプは、スクリプト内で使用され、コンテンツに対して保持されないので、プロキシ経由ではなく直接使用されます。
完了 byline.html
以下:
<!--/* byline.html */-->
<div data-sly-use.byline="com.adobe.aem.guides.wknd.core.models.Byline"
data-sly-use.placeholderTemplate="core/wcm/components/commons/v1/templates.html"
data-sly-test.hasContent="${!byline.empty}"
class="cmp-byline">
<div class="cmp-byline__image"
data-sly-resource="${ '.' @ resourceType = 'core/wcm/components/image/v2/image' }">
</div>
<h2 class="cmp-byline__name">${byline.name}</h2>
<p class="cmp-byline__occupations">${byline.occupations @ join=', '}</p>
</div>
<sly data-sly-call="${placeholderTemplate.placeholder @ isEmpty=!hasContent}"></sly>
コードベースをローカルの AEM インスタンスにデプロイします。変更が加えられたため core
および ui.apps
両方のモジュールをデプロイする必要があります。
$ cd aem-guides-wknd/ui.apps
$ mvn clean install -PautoInstallPackage
$ cd ../core
$ mvn clean install -PautoInstallBundle
AEM 6.5/6.4 にデプロイする場合は、 classic
プロファイル:
$ cd ../core
$ mvn clean install -PautoInstallBundle -Pclassic
また、Maven プロファイルを使用して、ルートからプロジェクト全体を構築することもできます autoInstallSinglePackage
ただし、これにより、ページ上のコンテンツの変更が上書きされる場合があります。 これは、 ui.content/src/main/content/META-INF/vault/filter.xml
は、既存のAEMコンテンツをきれいに上書きするように、チュートリアルのスターターコードを変更しました。 実際のシナリオでは、これは問題にはなりません。
アップデートをデプロイした後、 LA スケートパークスの究極ガイド ページ、またはこの章で既に署名コンポーネントを追加した場所。
この 画像, 名前、および 職業 が表示され、スタイルが設定されていないが、Byline コンポーネントが動作している。
AEM Web コンソールの Sling Models Status 表示には、AEM に登録されたすべての Sling Model が表示されます。署名 Sling Model は、このリストを確認することで、インストールされ、認識されていることを検証できます。
この BylineImpl がこのリストに表示されない場合は、Sling モデルの注釈に問題があるか、Sling モデルが登録済みの Sling モデルパッケージ (com.adobe.aem.guides.wknd.core.models
) をコアプロジェクトに追加しました。
http://localhost:4502/system/console/status-slingmodels
署名コンポーネントは、署名コンポーネントのクリエイティブデザインに沿ってスタイルを設定する必要があります。これは、AEMが ui.frontend Maven サブプロジェクト。
署名コンポーネントのデフォルトスタイルを追加します。
IDE とに戻ります。 ui.frontend ~の下に投影する /src/main/webpack/components
:
という名前の新しいファイルを作成します。 _byline.scss
.
署名実装 CSS(SCSS として書き込む)を _byline.scss
:
.cmp-byline {
$imageSize: 60px;
.cmp-byline__image {
float: left;
/* This class targets a Core Component Image CSS class */
.cmp-image__image {
width: $imageSize;
height: $imageSize;
border-radius: $imageSize / 2;
object-fit: cover;
}
}
.cmp-byline__name {
font-size: $font-size-medium;
font-family: $font-family-serif;
padding-top: 0.5rem;
margin-left: $imageSize + 25px;
margin-bottom: .25rem;
margin-top:0rem;
}
.cmp-byline__occupations {
margin-left: $imageSize + 25px;
color: $gray;
font-size: $font-size-xsmall;
text-transform: uppercase;
}
}
ターミナルを開き、 ui.frontend
モジュール。
を開始します。 watch
次の npm コマンドを使用してプロセスを実行します。
$ cd ui.frontend/
$ npm run watch
ブラウザーに戻り、 LA SkateParks 記事. コンポーネントの更新済みのスタイルが表示されます。
古い CSS が提供されないようにブラウザーのキャッシュをクリアし、署名コンポーネントでページを更新して完全なスタイルを取得する必要が生じる場合があります。
Adobe Experience Managerを使用してカスタムコンポーネントを最初から作成しました。
引き続き、署名 Java コードの JUnit テストを記述して、すべてが正しく開発され、実装されたビジネスロジックが正しく完了していることを確認し、AEMコンポーネントの開発について学びます。
で完成したコードを表示する GitHub または、Git ブラッチ上のローカルのにコードを確認してデプロイします。 tutorial/custom-component-solution
.
tutorial/custom-component-solution
分岐