SPA コンポーネントを AEM コンポーネントへのマッピング map-components

IMPORTANT
SPA エディターは、新しいプロジェクトでは非推奨(廃止予定)になりました。アドビでは既存のプロジェクトに対して引き続きサポートしますが、新しいプロジェクトには使用しないでください。AEM でヘッドレスコンテンツの管理に推奨されるエディターは次のようになりました。

AEM SPA エディター JS SDK を使用して Angular コンポーネントを Adobe Experience Manager(AEM)コンポーネントにマッピングする方法について説明します。 コンポーネントマッピングを使用すると、AEM SPA エディター内で、従来の AEM オーサリングと同様に、SPA コンポーネントを動的に更新できます。

この章では、AEM JSON モデル API について詳しく説明し、AEM コンポーネントによって公開された JSON コンテンツを prop として Angular コンポーネントに自動的に挿入する方法についても説明します。

目的

  1. AEM コンポーネントを SPA コンポーネントにマッピングする方法について説明します。
  2. コンテナ​コンポーネントと​ コンテンツ ​コンポーネントの違いを理解します。
  3. 既存の AEM コンポーネントにマッピングされる新規の Angular コンポーネントを作成します。

作成する内容

この章では、提供されたText SPA コンポーネントが AEM Text コンポーネントにどのようにマッピングされるかを調べます。 SPA で使用し AEM でオーサリングできる新規の Image SPA コンポーネントが作成されます。 レイアウトコンテナ​および​ テンプレートエディター ​ポリシーの標準機能を使用して、わずかに外観が異なるビューを作成することもできます。

この章の最終的なオーサリングサンプル

前提条件

ローカル開発環境を設定するために必要なツールや説明を確認してください。

コードの取得

  1. このチュートリアルの出発点となるものを Git からダウンロードします。

    code language-shell
    $ git clone git@github.com:adobe/aem-guides-wknd-spa.git
    $ cd aem-guides-wknd-spa
    $ git checkout Angular/map-components-start
    
  2. Maven を使用してコードベースをローカルの AEM インスタンスにデプロイします。

    code language-shell
    $ mvn clean install -PautoInstallSinglePackage
    

    AEM 6.x を使用する場合は、以下の classic プロファイルを追加します。

    code language-shell
    $ mvn clean install -PautoInstallSinglePackage -Pclassic
    

完成したコードは、GitHub で確認するか、またはブランチ Angular/map-components-solution に切り替えてコードをローカルで確認します。

マッピングアプローチ

基本的な概念は、SPA コンポーネントを AEM コンポーネントにマッピングすることです。 AEM コンポーネントは、サーバーサイドで実行され、JSON モデル API の一部としてコンテンツを書き出します。 JSON コンテンツは、ブラウザーでクライアントサイドを実行している SPA によって使用されます。 SPA コンポーネントとAEM コンポーネント間の1:1 マッピングが作成されます。

AEM コンポーネントから Angular コンポーネントへのマッピングの概要

AEM コンポーネントから Angular コンポーネントへのマッピングの概要

テキストコンポーネントを検査する

AEM プロジェクトアーキタイプは、AEM テキストコンポーネントにマッピングされる Text コンポーネントを提供します。 これは、AEM から​ コンテンツ ​をレンダリングするという、コンテンツ​コンポーネントの例です。

コンポーネントの動作を見てみましょう。

JSON モデルを調べる

  1. SPA のコードを調べる前に、AEM が提供する JSON モデルを理解しておくことが重要です。 コアコンポーネントライブラリに移動し、テキストコンポーネントのページを表示します。 コアコンポーネントライブラリには、すべての AEM コアコンポーネントの例が記載されています。

  2. 例の 1 つである JSON タブを選択します。

    テキスト JSON モデル

    textrichText、および :type の 3 つのプロパティが表示されます。

    :type は、AEM コンポーネントの sling:resourceType(またはパス)をリストする予約済みのプロパティです。 :type の値は、AEM コンポーネントを SPA コンポーネントにマップするために使用されるものです。

    text および richText は、SPA コンポーネントに公開される追加のプロパティです。

テキストコンポーネントの検査

  1. 新しいターミナルウィンドウを開き、プロジェクト内の ui.frontend フォルダーに移動します。 npm install の後に npm start を実行して、webpack 開発サーバー​を起動します。

    code language-shell
    $ cd ui.frontend
    $ npm run start:mock
    

    ui.frontend モジュールは現在、モック JSON モデルを使用するように設定されています。

  2. http://localhost:4200/content/wknd-spa-angular/us/en/home.htmlに新しいブラウザーウィンドウが開きます

    モックコンテンツを使用した webpack 開発サーバー

  3. 任意の IDE で、WKND SPA 用の AEM プロジェクトを開きます。 ui.frontend モジュールを展開し、ui.frontend/src/app/components/text/text.component.ts の下の text.component.ts ファイルを開きます。

    Text.js Angular コンポーネントのソースコード

  4. 最初に検査する領域は、35 行目までの class TextComponent です。

    code language-js
    export class TextComponent {
        @Input() richText: boolean;
        @Input() text: string;
        @Input() itemName: string;
    
        @HostBinding('innerHtml') get content() {
            return this.richText
            ? this.sanitizer.bypassSecurityTrustHtml(this.text)
            : this.text;
        }
        @HostBinding('attr.data-rte-editelement') editAttribute = true;
    
        constructor(private sanitizer: DomSanitizer) {}
    }
    

    @Input() デコレーターは、先ほど確認した、マッピング済み JSON オブジェクトを通じて値が設定されるフィールドの宣言に使用されます。

    @HostBinding('innerHtml') get content() は、this.text の値から作成したテキストコンテンツを公開するメソッドです。 コンテンツが(this.richText フラグで決まる)リッチテキストの場合、Angular のビルトインのセキュリティは無視されます。 Angular の DomSanitizer は、未処理の HTMLを「スクラブ」し、クロスサイトスクリプティングの脆弱性を防ぐために使用されます。 このメソッドは、@HostBinding デコレーターを使用して innerHtml プロパティにバインドされます。

  5. 次に、24 行目までの TextEditConfig を調べます。

    code language-js
    const TextEditConfig = {
        emptyLabel: 'Text',
        isEmpty: cqModel =>
            !cqModel || !cqModel.text || cqModel.text.trim().length < 1
    };
    

    上記のコードは AEM オーサー環境で、プレースホルダーをレンダリングするタイミングを決定する役割を果たします。 この isEmpty メソッドが true を返した場合、プレースホルダーがレンダリングされます。

  6. 最後に、53 行目までの MapTo 呼び出しを確認します。

    code language-js
    MapTo('wknd-spa-angular/components/text')(TextComponent, TextEditConfig );
    

    MapTo は、AEM SPA エディター JS SDK(@adobe/cq-angular-editable-components)から提供されます。 パス wknd-spa-angular/components/text は、AEM コンポーネントの sling:resourceType を表します。 このパスは、前に確認した JSON モデルによって公開された :type と一致します。 MapTo は JSON モデルの応答を解析し、正しい値を SPA コンポーネントの @Input() 変数に渡します。

    AEM Text コンポーネントの定義は ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/text にあります。

  7. ui.frontend/src/mocks/json/en.model.jsonen.model.json を変更して実験します。

    62 行目までで、H1 および u タグを使用するように最初の Text 値を更新します。

    code language-json
        "text": {
            "text": "<h1><u>Hello World!</u></h1>",
            "richText": true,
            ":type": "wknd-spa-angular/components/text"
        }
    

    ブラウザーに戻り、webpack 開発サーバー​から提供される効果を確認します。

    更新されたテキストモデル

    richText プロパティを truefalse の間で切り替えて、動作中のレンダリングロジックを確認します。

  8. ui.frontend/src/app/components/text/text.component.htmltext.component.html を調べます。

    コンポーネントのコンテンツ全体が innerHTML プロパティで設定されるので、このファイルは空です。

  9. ui.frontend/src/app/app.module.tsapp.module.ts を調べます。

    code language-js
    @NgModule({
    imports: [
        BrowserModule,
        SpaAngularEditableComponentsModule,
        AppRoutingModule
    ],
    providers: [ModelManagerService, { provide: APP_BASE_HREF, useValue: '/' }],
    declarations: [AppComponent, TextComponent, PageComponent, HeaderComponent],
    entryComponents: [TextComponent, PageComponent],
    bootstrap: [AppComponent]
    })
    export class AppModule {}
    

    TextComponent は明示的に組み込まれるのではなく、AEM SPA エディター JS SDK から提供される AEMResponsiveGridComponent を通じて動的に組み込まれます。 したがって、app.module.tsentryComponents 配列にリストされている必要があります。

画像コンポーネントの作成

次に、AEM の画像コンポーネントにマッピングされる Image Angular コンポーネントを作成します。 この Image コンポーネントは、コンテンツ​コンポーネントのもう一つの例です。

JSO の検査

SPA コードを調べる前に、AEM が指定した JSON モデルを調べます。

  1. コアコンポーネントライブラリに置かれた画像の例に移動します。

    画像コアコンポーネントの JSON

    srcalttitle のプロパティは、SPA Image コンポーネントの入力に使用されます。

    note note
    NOTE
    公開された他の画像プロパティ(lazyEnabledwidths)があり、これを使用して開発者は、適応型の遅延読み込みコンポーネントを作成することができます。 このチュートリアルで作成されたコンポーネントはシンプルで、これらの詳細なプロパティを使用​しません
  2. IDE に戻り、en.model.jsonui.frontend/src/mocks/json/en.model.json)を開きます。 これはプロジェクトのまったく新しいコンポーネントなので、画像 JSON の「モック」を作成する必要があります。

    70 行目までで、image モデルの JSON エントリを追加し(2 番目の text_386303036 の後にコンマ , を入れることを忘れないでください)、:itemsOrder 配列を更新します。

    code language-json
    ...
    ":items": {
                ...
                "text_386303036": {
                    "text": "<p>A new text component.</p>\r\n",
                    "richText": true,
                    ":type": "wknd-spa-angular/components/text"
                    },
                "image": {
                    "alt": "Rock Climber in New Zealand",
                    "title": "Rock Climber in New Zealand",
                    "src": "/mocks/images/adobestock-140634652.jpeg",
                    ":type": "wknd-spa-angular/components/image"
                }
            },
            ":itemsOrder": [
                "text",
                "text_386303036",
                "image"
            ],
    

    このプロジェクトには、webpack 開発サーバー​と共に使用されるサンプル画像(/mock-content/adobestock-140634652.jpeg)が含まれています。

    すべての en.model.json については、こちらを参照してください。

  3. コンポーネントに表示するストック写真を追加します。

    ui.frontend/src/mocks の下に images という名前の新しいフォルダーを作成します。 adobestock-140634652.jpeg をダウンロードし、新しく作成した images フォルダーに格納します。 必要に応じて、自分の画像を自由に使用できます。

画像コンポーネントの実装

  1. webpack 開発サーバー​が起動されていれば停止します。

  2. ui.frontend フォルダー内から Angular CLI ng generate component コマンドを実行して、新しい画像コンポーネントを作成します。

    code language-shell
    $ ng generate component components/image
    
  3. IDE で、image.component.tsui.frontend/src/app/components/image/image.component.ts)を開いて、次のように更新します。

    code language-js
    import {Component, Input, OnInit} from '@angular/core';
    import {MapTo} from '@adobe/cq-angular-editable-components';
    
    const ImageEditConfig = {
    emptyLabel: 'Image',
    isEmpty: cqModel =>
        !cqModel || !cqModel.src || cqModel.src.trim().length < 1
    };
    
    @Component({
    selector: 'app-image',
    templateUrl: './image.component.html',
    styleUrls: ['./image.component.scss']
    })
    export class ImageComponent implements OnInit {
    
    @Input() src: string;
    @Input() alt: string;
    @Input() title: string;
    
    constructor() { }
    
    get hasImage() {
        return this.src && this.src.trim().length > 0;
    }
    
    ngOnInit() { }
    }
    
    MapTo('wknd-spa-angular/components/image')(ImageComponent, ImageEditConfig);
    

    ImageEditConfig は、src プロパティに値が設定されているかどうかに応じて、AEM でオーサープレースホルダーをレンダリングするかどうかを決定するための設定です。

    srcalt および title@Input() は、JSON API からマッピングされるプロパティです。

    hasImage() は、画像をレンダリングするかどうかを指定するメソッドです。

    MapTo は、SPA コンポーネントを、ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/image にある AEM コンポーネントにマッピングします。

  4. image.component.html を開いて、次のように更新します。

    code language-html
    <ng-container *ngIf="hasImage">
        <img class="image" [src]="src" [alt]="alt" [title]="title"/>
    </ng-container>
    

    これにより、hasImagetrue を返す場合、<img> 要素がレンダリングされるようになります。

  5. image.component.scss を開いて、次のように更新します。

    code language-scss
    :host-context {
        display: block;
    }
    
    .image {
        margin: 1rem 0;
        width: 100%;
        border: 0;
    }
    
    note note
    NOTE
    :host-context ルールは、AEM SPA エディターのプレースホルダーが正しく機能するために​ 重要 ​です。 AEM ページエディターで作成するすべての SPA コンポーネントには、少なくともこのルールが必要です。
  6. app.module.ts を開いて、entryComponents 配列に ImageComponent を追加します。

    code language-js
    entryComponents: [TextComponent, PageComponent, ImageComponent],
    

    TextComponent と同様に、ImageComponent は動的に読み込まれるので、entryComponents 配列に含める必要があります。

  7. webpack 開発サーバー​を起動して、ImageComponent がレンダリングされることを確認します。

    code language-shell
    $ npm run start:mock
    

    モックに追加された画像

    SPA に追加された画像

    note note
    NOTE
    ボーナスチャレンジtitle の値を画像の下のキャプションとして表示する新しいメソッドを実装します。

AEM でのポリシーの更新

ImageComponent コンポーネントは、webpack 開発サーバー​でのみ表示されます。 次に、更新された SPA を AEM にデプロイし、テンプレートポリシーを更新します。

  1. webpack 開発サーバー​を停止し、プロジェクトの​ ルート ​から、Maven スキルを使用して変更内容を AEM にデプロイします。

    code language-shell
    $ cd aem-guides-wknd-spa
    $ mvn clean install -PautoInstallSinglePackage
    
  2. AEM 開始画面から、ツールテンプレートWKND SPA Angular に移動します。

    SPA ページ​を選択して編集します。

    SPA ページテンプレートの編集

  3. レイアウトコンテナ​を選択し、「ポリシー」アイコンをクリックしてポリシーを編集します。

    レイアウトコンテナポリシー

  4. 許可されたコンポーネントWKND SPA Angular - コンテンツ​の下で、画像​コンポーネントにチェックを入れます。

    選択された画像コンポーネント

    デフォルトのコンポーネントマッピングを追加​の下で、画像 - WKND SPA Angular - コンテンツ​コンポーネントを選択します。

    デフォルトコンポーネントを設定

    image/*mime タイプ​を入力します。

    完了」をクリックして、ポリシーの更新を保存します。

  5. レイアウトコンテナ​で、テキスト​コンポーネント用の​ ポリシー ​アイコンをクリックします。

    テキストコンポーネントポリシーアイコン

    WKND SPA テキスト​という名前の新しいポリシーを作成します。 プラグイン書式設定​の下にあるすべてのボックスをオンにして、次の追加の書式設定オプションを有効にします。

    RTE フォーマットを有効にする

    プラグイン段落スタイル​の下で、「段落スタイルを有効にする」チェックボックスをオンにします。

    段落スタイルを有効にする

    完了」をクリックしてポリシーの更新を保存します。

  6. ホームページ http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.htmlに移動します。

    また、Text コンポーネントを編集して、全画面表示​モードで追加の段落スタイルを追加できます。

    全画面表示のリッチテキスト編集

  7. また、画像を​ アセットファインダー ​からドラッグ&ドロップできます。

    画像をドラッグ&ドロップする

  8. AEM Assets を介して独自の画像を追加するか、標準の WKND 参照サイトの完成したコードベースをインストールします。 WKND 参照サイトには、WKND SPAで再利用できる画像が多数含まれています。 パッケージは、AEM のパッケージマネージャーを使用してインストールできます。

    パッケージマネージャーによる wknd.all のインストール

レイアウトコンテナを調べる

レイアウトコンテナ​のサポートは、AEM SPA Editor SDK によって自動的に提供されます。 レイアウトコンテナ​は、その名前が示すように​ コンテナ ​コンポーネントです。 コンテナコンポーネントは、他の​コンポーネントを表す JSON 構造を受け入れ、それらを動的にインスタンス化するコンポーネントです。

ここでは、レイアウトコンテナをさらに詳しく調べます。

  1. IDE で ui.frontend/src/app/components/responsive-gridresponsive-grid.component.ts を開きます。

    code language-js
    import { AEMResponsiveGridComponent,MapTo } from '@adobe/cq-angular-editable-components';
    
    MapTo('wcm/foundation/components/responsivegrid')(AEMResponsiveGridComponent);
    

    AEMResponsiveGridComponent はAEM SPA Editor SDK の一部として実装され、import-components を介してプロジェクトに含まれます。

  2. ブラウザーで、http://localhost:4502/content/wknd-spa-angular/us/en.model.jsonに移動します

    JSON モデル API - レスポンシブグリッド

    レイアウトコンテナ​コンポーネントの sling:resourceTypewcm/foundation/components/responsivegrid であり、Text コンポーネントや Image コンポーネントと同様に、:type プロパティを使用して SPA エディターによって認識されます。

    レイアウトモードを使用してコンポーネントのサイズを変更するのと同じ機能が、SPA エディターで利用できます。

  3. http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.htmlに戻ります。 さらに​ 画像 ​コンポーネントを追加し、レイアウト​オプションを使用してサイズを変更してみてください。

    レイアウトモードを使用した画像のサイズ変更

  4. JSON モデル http://localhost:4502/content/wknd-spa-angular/us/en.model.jsonを再度開き、JSONの一部としてcolumnClassNamesを確認します。

    列クラス名

    クラス名 aem-GridColumn--default--4 は、12 列のグリッドに基づいて幅が 4 列に設定されている必要があることを示します。 レスポンシブグリッドについて詳しくは、こちらをご覧ください。

  5. IDE に戻り、ui.apps モジュールで、ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/clientlibs/clientlib-grid で定義されたクライアントサイドライブラリがあります。 less/grid.less ファイルを開きます。

    このファイルは、レイアウトコンテナ​で使用されるブレークポイント(defaulttabletphone)を特定します。 このファイルは、プロジェクトの仕様に応じてカスタマイズされます。 現在、ブレークポイントは 1200px および 650px に設定されています。

  6. Text コンポーネントのレスポンシブ機能と、更新されたリッチテキストポリシーを使用して、次のようなビューを作成できます。

    章サンプルの最終オーサリング

おめでとうございます。 congratulations

これで、SPA コンポーネントを AEM コンポーネントにマッピングする方法を学習し、新しい Image コンポーネントを実装しました。 また、レイアウトコンテナ​のレスポンシブ機能について探索する機会もありました。

完成したコードを GitHub で確認する、または、ブランチ Angular/map-components-solution に切り替えて、コードをローカルでチェックアウトします。

次の手順 next-steps

ナビゲーションとルーティング - SPA Editor SDK を使用して AEM ページにマッピングすることで、SPA の複数のビューをサポートする方法について説明します。 Angular ルートを使用して動的ナビゲーションを実装し、既存のヘッダーコンポーネントに追加します。

(ボーナス)ソースコントロールに対する設定の保持 bonus

多くの場合、特に AEM プロジェクトの開始時に、テンプレートや関連するコンテンツポリシーなどの設定をソースコントロールに保持すると便利です。 これにより、すべての開発者が同じセットのコンテンツと設定に対して作業することが保証され、環境間の一貫性がさらに確保できます。 プロジェクトが一定の成熟度に達すると、テンプレートの管理作業を特別なパワーユーザーグループに引き継ぐことができます。

次のいくつかの手順は、Visual Studio Code IDE と VSCode AEM Sync を使用して行われますが、AEM のローカルインスタンスからコンテンツを​ 取り込み ​または​ 読み込む ​ように設定した任意のツールと IDE を使用して行うことができます。

  1. Visual Studio Code IDE で、Marketplace 拡張機能を介して VSCode AEM Sync がインストールされていることを確認します。

    VSCode AEM Sync

  2. プロジェクトエクスプローラー内の ui.content モジュールをを展開して、/conf/wknd-spa-angular/settings/wcm/templates に移動します。

  3. templates フォルダーを​ 右クリック ​し、AEM サーバーから読み込む​を選択します。

    VSCode インポートテンプレート

  4. コンテンツを読み込む手順を繰り返しますが、/conf/wknd-spa-angular/settings/wcm/policies に置かれた​ ポリシー ​フォルダーを選択します。

  5. ui.content/src/main/content/META-INF/vault/filter.xml にある filter.xml ファイルを調べます。

    code language-xml
    <!--ui.content filter.xml-->
    <?xml version="1.0" encoding="UTF-8"?>
     <workspaceFilter version="1.0">
         <filter root="/conf/wknd-spa-angular" mode="merge"/>
         <filter root="/content/wknd-spa-angular" mode="merge"/>
         <filter root="/content/dam/wknd-spa-angular" mode="merge"/>
         <filter root="/content/experience-fragments/wknd-spa-angular" mode="merge"/>
     </workspaceFilter>
    

    filter.xml ファイルは、パッケージと共にインストールされるノードのパスを識別する役割を果たします。 各フィルターの mode="merge" に注目してください。これは、既存のコンテンツは変更されず、新しいコンテンツのみが追加されることを示しています。 コンテンツ作成者がこれらのパスを更新する可能性があるので、コードのデプロイメントでは、コンテンツを上書き​しません。 フィルター要素の操作の詳細については、FileVault ドキュメントを参照してください。

    ui.content/src/main/content/META-INF/vault/filter.xmlui.apps/src/main/content/META-INF/vault/filter.xml を比較して、各モジュールによって管理される様々なノードを理解します。

recommendation-more-help
e25b6834-e87f-4ff3-ba56-4cd16cdfdec4