ナビゲーションとルーティングの追加

AEM PagesとSPA Editor SDKを使用した、SPAの複数のビューのサポート方法について説明します。 動的ナビゲーションは、Angularルートを使用して実装され、既存のヘッダーコンポーネントに追加されます。

目的

  1. SPA Editorを使用する場合に使用できるSPAモデルのルーティングオプションを理解します。
  2. Angularルーティングを使用してSPAの異なるビュー間を移動する方法を説明します。
  3. AEMページ階層によって駆動される動的ナビゲーションを実装します。

作成する内容

この章では、既存のHeaderコンポーネントにナビゲーションメニューを追加します。 ナビゲーションメニューは、AEMページ階層によって駆動され、ナビゲーションコアコンポーネントが提供するJSONモデルを使用します。

ナビゲーションの実装

前提条件

ローカル開発環境の設定に必要なツールと手順を確認します。

コードの取得

  1. このチュートリアルの開始点をGitからダウンロードします。

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

    $ mvn clean install -PautoInstallSinglePackage
    

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

    $ mvn clean install -PautoInstallSinglePackage -Pclassic
    
  3. 従来のWKNDリファレンスサイト用に完成したパッケージをインストールします。 WKND参照サイトから提供された画像は、WKND SPAで再利用されます。 パッケージは、AEM Package Managerを使用してインストールできます。

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

GitHubで完成したコードをいつでも表示したり、ブランチAngular/navigation-routing-solutionに切り替えてコードをローカルでチェックアウトしたりできます。

Inspect HeaderComponentの更新

以前の章では、HeaderComponentコンポーネントは、app.component.htmlを介して含まれる純粋なAngularコンポーネントとして追加されました。 この章では、HeaderComponentコンポーネントをアプリから削除し、テンプレートエディターを使用して追加します。 これにより、ユーザーはAEM内からHeaderComponentのナビゲーションメニューを設定できます。

メモ

この章を開始するために、コードベースに対して、いくつかのCSSおよびJavaScriptの更新が既におこなわれています。 コード変更の​すべて​ではなく、コア概念に焦点を当てます。 ここでの全変更を確認できます。

  1. 任意のIDEで、この章のSPAスタータープロジェクトを開きます。

  2. ui.frontendモジュールの下で、次の場所にあるファイルheader.component.tsを検査します。ui.frontend/src/app/components/header/header.component.ts.

    コンポーネントをAEMコンポーネントwknd-spa-angular/components/headerにマッピングできるように、HeaderEditConfigMapToを追加するなど、いくつかの更新がおこなわれました。

    /* header.component.ts */
    ...
    const HeaderEditConfig = {
        ...
    };
    
    @Component({
    selector: 'app-header',
    templateUrl: './header.component.html',
    styleUrls: ['./header.component.scss']
    })
    export class HeaderComponent implements OnInit {
    @Input() items: object[];
        ...
    }
    ...
    MapTo('wknd-spa-angular/components/header')(withRouter(Header), HeaderEditConfig);
    

    items@Input()注釈に注意してください。 items は、AEMから渡されたナビゲーションオブジェクトの配列を含みます。

  3. ui.appsモジュールで、AEM Headerコンポーネントのコンポーネント定義を検査します。ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/header/.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="Header"
        sling:resourceSuperType="wknd-spa-angular/components/navigation"
        componentGroup="WKND SPA Angular - Structure"/>
    

    AEM Headerコンポーネントは、sling:resourceSuperTypeプロパティを介してナビゲーションコアコンポーネントのすべての機能を継承します。

HeaderComponentをSPAテンプレートに追加する

  1. ブラウザーを開き、 AEM http://localhost:4502/にログインします。 開始コードベースは、既にデプロイされている必要があります。

  2. SPA Page Template​に移動します。http://localhost:4502/editor.html/conf/wknd-spa-angular/settings/wcm/templates/spa-page-template/structure.html.

  3. 最も外側にある​ルートレイアウトコンテナ​を選択し、ポリシー​アイコンをクリックします。 オーサリング用に​レイアウトコンテナ​をロック解除して選択する場合は、​に注意してください。

    ルートレイアウトコンテナポリシーアイコンを選択します

  4. 現在のポリシーをコピーし、SPA Structure​という名前の新しいポリシーを作成します。

    SPA構造ポリシー

    許可されているコンポーネント > 一般 」で、レイアウトコンテナ​コンポーネントを選択します。

    許可されているコンポーネント > WKND SPAANGULAR- STRUCTURE​の下で、ヘッダー​コンポーネントを選択します。

    ヘッダーコンポーネントを選択

    許可されているコンポーネント / WKND SPAANGULAR — コンテンツ 」で、「画像」および「テキスト」コンポーネントを選択します。 合計4つのコンポーネントを選択する必要があります。

    完了」をクリックして、変更を保存します。

  5. ページを更新します。​ロックされていない​レイアウトコンテナ​の上に、ヘッダー​コンポーネントを追加します。

    テンプレートへのヘッダーコンポーネントの追加

  6. ヘッダー​コンポーネントを選択し、ポリシー​アイコンをクリックしてポリシーを編集します。

    ヘッダーポリシーをクリック

  7. ポリシーのタイトル​を​"WKND SPA Header"​にして新しいポリシーを作成します。

    プロパティ​の下:

    • ナビゲーションルート​を/content/wknd-spa-angular/us/enに設定します。
    • Exclude Root Levels​を​1​に設定します。
    • すべての子ページを収集 」のチェックを外します。
    • ナビゲーション構造の深さ​を​3​に設定します。

    ヘッダーポリシーの設定

    これにより、/content/wknd-spa-angular/us/enの下の2レベルのナビゲーションが収集されます。

  8. 変更を保存すると、テンプレートの一部として入力されたHeaderが表示されます。

    入力済みのヘッダーコンポーネント

子ページの作成

次に、AEMで別のビューとして機能する追加のページを作成します。 また、AEMが提供するJSONモデルの階層構造も調べます。

  1. サイト​コンソールに移動します。http://localhost:4502/sites.html/content/wknd-spa-angular/us/en/home. WKND SPAAngularホームページ​を選択し、作成 / ページ​をクリックします。

    ページを新規作成

  2. テンプレート」で、「SPAページ」を選択します。 「プロパティ」で、タイトル​に​「ページ1」​を、名前に​「ページ1」​を入力します。

    最初のページのプロパティを入力します

    作成」をクリックし、ダイアログポップアップで「開く」をクリックしてAEM SPAエディターでページを開きます。

  3. 新しい​テキスト​コンポーネントをメインの​レイアウトコンテナ​に追加します。 コンポーネントを編集し、次のテキストを入力します。"ページ1"​は、RTEと​H1​要素を使用します(段落要素を変更するには、フルスクリーンモードにする必要があります)。

    サンプルコンテンツページ1

    画像などのコンテンツを自由に追加できます。

  4. AEM Sitesコンソールに戻り、上記の手順を繰り返し、"Page 2"​という名前の2番目のページを​Page 1​の兄弟として作成します。 識別しやすいように、ページ2​にコンテンツを追加します。

  5. 最後に、3番目のページ​"Page 3"​を、ページ2​の​​として作成します。 完了すると、サイト階層は次のようになります。

    サイト階層のサンプル

  6. 新しいタブで、AEMが提供するJSONモデルAPIを開きます。http://localhost:4502/content/wknd-spa-angular/us/en.model.json. このJSONコンテンツは、SPAが最初に読み込まれたときにリクエストされます。 外側の構造は次のようになります。

    {
    "language": "en",
    "title": "en",
    "templateName": "spa-app-template",
    "designPath": "/libs/settings/wcm/designs/default",
    "cssClassNames": "spa page basicpage",
    ":type": "wknd-spa-angular/components/spa",
    ":items": {},
    ":itemsOrder": [],
    ":hierarchyType": "page",
    ":path": "/content/wknd-spa-angular/us/en",
    ":children": {
        "/content/wknd-spa-angular/us/en/home": {},
        "/content/wknd-spa-angular/us/en/home/page-1": {},
        "/content/wknd-spa-angular/us/en/home/page-2": {},
        "/content/wknd-spa-angular/us/en/home/page-2/page-3": {}
        }
    }
    

    :childrenの下に、作成された各ページのエントリが表示されます。 すべてのページのコンテンツは、この最初のJSONリクエストに含まれます。 ナビゲーションルーティングが実装されると、コンテンツは既にクライアント側で使用可能なので、SPAの以降のビューはすばやく読み込まれます。

    最初のJSONリクエストでSPAのコンテンツの​ALL​を読み込むと、最初のページ読み込みが遅くなるので、賢明ではありません。 次に、ページの階層の深さがどのように収集されるかを見てみましょう。

  7. 次の場所にある​SPA Root​テンプレートに移動します。http://localhost:4502/editor.html/conf/wknd-spa-angular/settings/wcm/templates/spa-app-template/structure.html.

    ページプロパティメニュー / ページポリシー​をクリックします。

    SPA Rootのページポリシーを開きます。

  8. SPA Root​テンプレートには、収集されるJSONコンテンツを制御するための追加の「階層構造」タブがあります。 構造の深さ​は、サイト階層の深さを決定し、ルート​の下の子ページを収集します。 「構造パターン」フィールドを使用して、正規表現に基づいて追加のページを除外することもできます。

    構造の深さ​を​"2"​に更新します。

    構造の深さの更新

    完了」をクリックして、ポリシーに対する変更を保存します。

  9. JSONモデルhttp://localhost:4502/content/wknd-spa-angular/us/en.model.jsonを再度開きます。

    {
    "language": "en",
    "title": "en",
    "templateName": "spa-app-template",
    "designPath": "/libs/settings/wcm/designs/default",
    "cssClassNames": "spa page basicpage",
    ":type": "wknd-spa-angular/components/spa",
    ":items": {},
    ":itemsOrder": [],
    ":hierarchyType": "page",
    ":path": "/content/wknd-spa-angular/us/en",
    ":children": {
        "/content/wknd-spa-angular/us/en/home": {},
        "/content/wknd-spa-angular/us/en/home/page-1": {},
        "/content/wknd-spa-angular/us/en/home/page-2": {}
        }
    }
    

    ページ3​のパスが削除されていることに注意してください。/content/wknd-spa-angular/us/en/home/page-2/page-3を最初のJSONモデルから取得します。

    後で、AEM SPA Editor SDKが追加コンテンツを動的に読み込む方法を確認します。

ナビゲーションの実装

次に、新しいNavigationComponentを使用してナビゲーションメニューを実装します。 header.component.htmlにコードを直接追加する方法もありますが、大きなコンポーネントを避ける方がよい方法です。 代わりに、後で再利用される可能性のあるNavigationComponentを実装します。

  1. AEM Headerコンポーネントによって公開されたJSONをhttp://localhost:4502/content/wknd-spa-angular/us/en.model.jsonで確認します。

    ...
    "header": {
        "items": [
        {
        "level": 0,
        "active": true,
        "path": "/content/wknd-spa-angular/us/en/home",
        "description": null,
        "url": "/content/wknd-spa-angular/us/en/home.html",
        "lastModified": 1589062597083,
        "title": "WKND SPA Angular Home Page",
        "children": [
                {
                "children": [],
                "level": 1,
                "active": false,
                "path": "/content/wknd-spa-angular/us/en/home/page-1",
                "description": null,
                "url": "/content/wknd-spa-angular/us/en/home/page-1.html",
                "lastModified": 1589429385100,
                "title": "Page 1"
                },
                {
                "level": 1,
                "active": true,
                "path": "/content/wknd-spa-angular/us/en/home/page-2",
                "description": null,
                "url": "/content/wknd-spa-angular/us/en/home/page-2.html",
                "lastModified": 1589429603507,
                "title": "Page 2",
                "children": [
                    {
                    "children": [],
                    "level": 2,
                    "active": false,
                    "path": "/content/wknd-spa-angular/us/en/home/page-2/page-3",
                    "description": null,
                    "url": "/content/wknd-spa-angular/us/en/home/page-2/page-3.html",
                    "lastModified": 1589430413831,
                    "title": "Page 3"
                    }
                ],
                }
            ]
            }
        ],
    ":type": "wknd-spa-angular/components/header"
    

    AEMページの階層性は、ナビゲーションメニューの入力に使用できるJSON形式でモデル化されています。 Headerコンポーネントはナビゲーションコアコンポーネントのすべての機能を継承し、JSONを通じて公開されたコンテンツは、Angular@Input注釈に自動的にマッピングされます。

  2. 新しいターミナルウィンドウを開き、SPAプロジェクトのui.frontendフォルダーに移動します。 angularCLIツールを使用して、新しいNavigationComponentを作成します。

    $ cd ui.frontend
    $ ng generate component components/navigation
    CREATE src/app/components/navigation/navigation.component.scss (0 bytes)
    CREATE src/app/components/navigation/navigation.component.html (25 bytes)
    CREATE src/app/components/navigation/navigation.component.spec.ts (656 bytes)
    CREATE src/app/components/navigation/navigation.component.ts (286 bytes)
    UPDATE src/app/app.module.ts (2032 bytes)
    
  3. 次に、新しく作成したcomponents/navigationディレクトリのAngularCLIを使用して、NavigationLinkという名前のクラスを作成します。

    $ cd src/app/components/navigation/
    $ ng generate class NavigationLink
    CREATE src/app/components/navigation/navigation-link.spec.ts (187 bytes)
    CREATE src/app/components/navigation/navigation-link.ts (32 bytes)
    
  4. 目的のIDEに戻り、/src/app/components/navigation/navigation-link.tsにあるnavigation-link.tsファイルを開きます。

    navigation-link.tsファイルを開きます。

  5. navigation-link.ts に以下を入力します。

    export class NavigationLink {
    
        title: string;
        path: string;
        url: string;
        level: number;
        children: NavigationLink[];
        active: boolean;
    
        constructor(data) {
            this.path = data.path;
            this.title = data.title;
            this.url = data.url;
            this.level = data.level;
            this.active = data.active;
            this.children = data.children.map( item => {
                return new NavigationLink(item);
            });
        }
    }
    

    これは、個々のナビゲーションリンクを表す単純なクラスです。 クラスコンストラクターでは、dataはAEMから渡されたJSONオブジェクトになります。 このクラスは、NavigationComponentHeaderComponentの両方で使用し、ナビゲーション構造を簡単に設定できます。

    データ変換は実行されません。このクラスは主にJSONモデルを強く入力するために作成されます。 this.childrenNavigationLink[]と型指定され、コンストラクタはchildren配列内の各項目に対して新しいNavigationLinkオブジェクトを再帰的に作成します。 HeaderのJSONモデルは階層的です。

  6. navigation-link.spec.ts ファイルを開きます。これはNavigationLinkクラスのテストファイルです。 次のように更新します。

    import { NavigationLink } from './navigation-link';
    
    describe('NavigationLink', () => {
        it('should create an instance', () => {
            const data = {
                children: [],
                level: 1,
                active: false,
                path: '/content/wknd-spa-angular/us/en/home/page-1',
                description: null,
                url: '/content/wknd-spa-angular/us/en/home/page-1.html',
                lastModified: 1589429385100,
                title: 'Page 1'
            };
            expect(new NavigationLink(data)).toBeTruthy();
        });
    });
    

    const dataは、前に検査したのと同じJSONモデルに従って、単一のリンクが検査されることに注意してください。 これは、堅牢な単体テストとは程遠いですが、NavigationLinkのコンストラクタをテストするのに十分です。

  7. navigation.component.ts ファイルを開きます。次のように更新します。

    import { Component, OnInit, Input } from '@angular/core';
    import { NavigationLink } from './navigation-link';
    
    @Component({
    selector: 'app-navigation',
    templateUrl: './navigation.component.html',
    styleUrls: ['./navigation.component.scss']
    })
    export class NavigationComponent implements OnInit {
    
        @Input() items: object[];
    
        constructor() { }
    
        get navigationLinks(): NavigationLink[] {
    
            if (this.items && this.items.length > 0) {
                return this.items.map(item => {
                    return new NavigationLink(item);
                });
            }
    
            return null;
        }
    
        ngOnInit() {}
    
    }
    

    NavigationComponent には、AEMの object[] JSONモ items デルであるという名前が必要です。このクラスは、NavigationLinkオブジェクトの配列を返す単一のメソッドget navigationLinks()を公開します。

  8. ファイルnavigation.component.htmlを開き、次のように更新します。

    <ul *ngIf="navigationLinks && navigationLinks.length > 0" class="navigation__group">
        <ng-container *ngTemplateOutlet="recursiveListTmpl; context:{ links: navigationLinks }"></ng-container>
    </ul>
    

    これにより、最初の<ul>が生成され、navigation.component.tsからget navigationLinks()メソッドが呼び出されます。 <ng-container>は、recursiveListTmplという名前のテンプレートを呼び出し、linksという名前の変数としてnavigationLinksに渡すために使用されます。

    次にrecursiveListTmplを追加します。

    <ng-template #recursiveListTmpl let-links="links">
        <li *ngFor="let link of links" class="{{'navigation__item navigation__item--' + link.level}}">
            <a [routerLink]="link.url" class="navigation__item-link" [title]="link.title" [attr.aria-current]="link.active">
                {{link.title}}
            </a>
            <ul *ngIf="link.children && link.children.length > 0">
                <ng-container *ngTemplateOutlet="recursiveListTmpl; context:{ links: link.children }"></ng-container>
            </ul>
        </li>
    </ng-template>
    

    ここでは、ナビゲーションリンクの残りのレンダリングが実装されます。 変数linkの型はNavigationLinkで、そのクラスで作成されるすべてのメソッド/プロパティを使用できます。 [routerLink] は、通常の属性の代わりに使用 href されます。これにより、全ページを更新することなく、アプリ内の特定のルートにリンクできます。

    現在のlinkに空でないchildren配列がある場合は、別の<ul>を作成することで、ナビゲーションの再帰的な部分も実装されます。

  9. navigation.component.spec.tsを更新して、RouterTestingModuleのサポートを追加します。

     ...
    + import { RouterTestingModule } from '@angular/router/testing';
     ...
     beforeEach(async(() => {
        TestBed.configureTestingModule({
    +   imports: [ RouterTestingModule ],
        declarations: [ NavigationComponent ]
        })
        .compileComponents();
     }));
     ...
    

    コンポーネントは[routerLink]を使用するので、RouterTestingModuleを追加する必要があります。

  10. navigation.component.scssを更新して、NavigationComponentに基本的なスタイルを追加します。

@import "~src/styles/variables";

$link-color: $black;
$link-hover-color: $white;
$link-background: $black;

:host-context {
    display: block;
    width: 100%;
}

.navigation__item {
    list-style: none;
}

.navigation__item-link {
    color: $link-color;
    font-size: $font-size-large;
    text-transform: uppercase;
    padding: $gutter-padding;
    display: flex;
    border-bottom: 1px solid $gray;

    &:hover {
        background: $link-background;
        color: $link-hover-color;
    }

}

ヘッダーコンポーネントの更新

NavigationComponentが実装されたので、HeaderComponentを更新して参照する必要があります。

  1. ターミナルを開き、SPAプロジェクト内のui.frontendフォルダーに移動します。 webpack開発サーバー​を起動します。

    $ npm start
    
  2. ブラウザータブを開き、http://localhost:4200/に移動します。

    AEMのローカルインスタンス(ui.frontend/proxy.conf.json)からJSONモデルをプロキシするように、webpack開発サーバー​を設定する必要があります。 これにより、チュートリアルの前の段階でからAEMで作成されたコンテンツに対して直接コードを作成できます。

    メニュー切り替え機能

    HeaderComponentには現在、メニュー切り替え機能が実装されています。 次に、ナビゲーションコンポーネントを追加します。

  3. 目的のIDEに戻り、ui.frontend/src/app/components/header/header.component.tsにあるheader.component.tsファイルを開きます。

  4. setHomePage()メソッドを更新して、ハードコードされたStringを削除し、AEMコンポーネントによって渡された動的propを使用します。

    /* header.component.ts */
    import { NavigationLink } from '../navigation/navigation-link';
    ...
     setHomePage() {
        if (this.hasNavigation) {
            const rootNavigationLink: NavigationLink = new NavigationLink(this.items[0]);
            this.isHome = rootNavigationLink.path === this.route.snapshot.data.path;
            this.homePageUrl = rootNavigationLink.url;
        }
    }
    ...
    

    NavigationLinkの新しいインスタンスは、AEMから渡されたナビゲーションJSONモデルのルートであるitems[0]に基づいて作成されます。 this.route.snapshot.data.path 現在のパスルートのAngularを返します。この値は、現在のルートが​Home Page​であるかどうかを判断するために使用されます。 this.homePageUrl を使用して、ロゴ にアンカーリンクを設​定します。

  5. header.component.htmlを開き、ナビゲーション用の静的プレースホルダーを新しく作成したNavigationComponentへの参照に置き換えます。

        <div class="header-navigation">
            <div class="navigation">
    -            Navigation Placeholder
    +           <app-navigation [items]="items"></app-navigation>
            </div>
        </div>
    

    [items]=items 属性は、から @Input() items ナビゲ HeaderComponent ーシ NavigationComponent ョンの作成先にを渡します。

  6. header.component.spec.tsを開き、NavigationComponentの宣言を追加します。

        /* header.component.spect.ts */
    +   import { NavigationComponent } from '../navigation/navigation.component';
    
        describe('HeaderComponent', () => {
        let component: HeaderComponent;
        let fixture: ComponentFixture<HeaderComponent>;
    
        beforeEach(async(() => {
            TestBed.configureTestingModule({
            imports: [ RouterTestingModule ],
    +       declarations: [ HeaderComponent, NavigationComponent ]
            })
            .compileComponents();
        }));
    

    NavigationComponentHeaderComponentの一部として使用されるので、テストベッドの一部として宣言する必要があります。

  7. 開いているファイルに変更を保存し、webpack開発サーバー​に戻ります。http://localhost:4200/

    完了したヘッダーナビゲーション

    メニューの切り替えをクリックしてナビゲーションを開くと、入力されたナビゲーションリンクが表示されます。 SPAの様々なビューに移動できるようになります。

SPAルーティングについて

ナビゲーションが実装されたので、AEMのルーティングを調べます。

  1. IDEで、ui.frontend/src/appにあるapp-routing.module.tsファイルを開きます。

    /* app-routing.module.ts */
    import { AemPageDataResolver, AemPageRouteReuseStrategy } from '@adobe/cq-angular-editable-components';
    import { NgModule } from '@angular/core';
    import { RouteReuseStrategy, RouterModule, Routes, UrlMatchResult, UrlSegment } from '@angular/router';
    import { PageComponent } from './components/page/page.component';
    
    export function AemPageMatcher(url: UrlSegment[]): UrlMatchResult {
        if (url.length) {
            return {
                consumed: url,
                posParams: {
                    path: url[url.length - 1]
                }
            };
        }
    }
    
    const routes: Routes = [
        {
            matcher: AemPageMatcher,
            component: PageComponent,
            resolve: {
                path: AemPageDataResolver
            }
        }
    ];
    @NgModule({
        imports: [RouterModule.forRoot(routes)],
        exports: [RouterModule],
        providers: [
            AemPageDataResolver,
            {
            provide: RouteReuseStrategy,
            useClass: AemPageRouteReuseStrategy
            }
        ]
    })
    export class AppRoutingModule {}
    

    routes: Routes = [];配列は、Angularコンポーネントマッピングへのルートまたはナビゲーションパスを定義します。

    AemPageMatcher は、カスタムAngularル ーターのUrlMatcherで、このAngularアプリケーションの一部であるAEMのページに「似ている」ものを照合します。

    PageComponent は、AEMのAngularを表すページコンポーネントで、一致したルートが呼び出されます。PageComponentはさらに検査されます。

    AemPageDataResolver(AEM SPA Editor JS SDKが提供する)カスタム Angularルータ ーResolverは、.html拡張を含むAEM内のパスであるルートURLを、拡張より短いページパスであるAEM内のリソースパスに変換するために使用します。

    例えば、AemPageDataResolverは、ルートのURL content/wknd-spa-angular/us/en/home.html/content/wknd-spa-angular/us/en/homeのパスに変換します。 これは、JSONモデルAPIのパスに基づいてページのコンテンツを解決するために使用されます。

    AemPageRouteReuseStrategyはAEM SPA Editor JS SDKで提供されるカスタムRouteReuseStrategyで、複数のル 🔗 ート間での再利用を PageComponent 防ぎます。そうしないと、ページ「B」に移動すると、ページ「A」のコンテンツが表示される場合があります。

  2. page.component.tsui.frontend/src/app/components/page/)ファイルを開きます。

    ...
    export class PageComponent {
        items;
        itemsOrder;
        path;
    
        constructor(
            private route: ActivatedRoute,
            private modelManagerService: ModelManagerService
        ) {
            this.modelManagerService
            .getData({ path: this.route.snapshot.data.path })
            .then(data => {
                this.path = data[Constants.PATH_PROP];
                this.items = data[Constants.ITEMS_PROP];
                this.itemsOrder = data[Constants.ITEMS_ORDER_PROP];
            });
        }
    }
    

    PageComponentは、AEMから取得したJSONを処理するために必要で、ルートをレンダリングするAngularコンポーネントとして使用されます。

    ActivatedRouteはAngularルーターモジュールで提供され、このAngularページコンポーネントインスタンスに読み込む必要があるAEMページのJSONコンテンツを示す状態を含みます。

    ModelManagerServiceでは、ルートに基づいてJSONデータを取得し、データをクラス変数、 、にマッピ pathング itemsしま itemsOrderす。これらは、次にAEMPageComponentに渡されます。

  3. ui.frontend/src/app/components/page/にあるpage.component.htmlファイルを開きます。

    <aem-page 
        class="structure-page" 
        [attr.data-cq-page-path]="path" 
        [cqPath]="path" 
        [cqItems]="items" 
        [cqItemsOrder]="itemsOrder">
    </aem-page>
    

    aem-page には、AEMPageComponentが含ま れています。変数pathitemsおよびitemsOrderAEMPageComponentに渡されます。 SPA Editor JavaScript SDKを介して提供されるAemPageComponentは、このデータを繰り返し処理し、 コンポーネントのマップのチュートリアルに示すように、JSONデータに基づいてAngularコンポーネントを動的にインスタンス化します。

    PageComponentは、実際にはAEMPageComponentの代わりにすぎません。JSONモデルをAngularコンポーネントに正しくマッピングするために、大部分の処理はAEMPageComponentです。

AEMでのSPAルーティングのInspect

  1. ターミナルを開き、起動した場合は​webpack開発サーバー​を停止します。 プロジェクトのルートに移動し、Mavenのスキルを使用してAEMにプロジェクトをデプロイします。

    $ cd aem-guides-wknd-spa
    $ mvn clean install -PautoInstallSinglePackage
    
    注意

    angularプロジェクトでは、非常に厳密なリントルールが有効になっています。 Mavenビルドに失敗した場合は、エラーを確認し、一覧に表示されているファイルで​Lintエラーを探します。」を選択します。リンターで見つかった問題を修正し、Mavenコマンドを再実行します。

  2. AEMのSPAホームページに移動します。http://localhost:4502/content/wknd-spa-angular/us/en/home.htmlを開き、ブラウザーの開発者ツールを開きます。 以下のスクリーンショットは、Google Chromeブラウザーからキャプチャされたものです。

    ページを更新すると、SPAルートである/content/wknd-spa-angular/us/en.model.jsonへのXHRリクエストが表示されます。 このチュートリアルで既に作成したSPAルートテンプレートの階層の深さ設定に基づいて、3つの子ページのみが含まれています。 ページ3​は含まれません。

    最初のJSONリクエスト — SPA Root

  3. 開発者ツールを開き、ページ3​に移動します。

    3ページ目のナビゲート

    新しいXHRリクエストが次の処理に対しておこなわれることを確認します。/content/wknd-spa-angular/us/en/home/page-2/page-3.model.json

    3ページ目のXHR要求

    AEM Model Managerは、ページ3​のJSONコンテンツが使用できないことを認識し、追加のXHRリクエストを自動的にトリガーします。

  4. 様々なナビゲーションリンクを使用してSPA内を移動し続けます。 追加のXHRリクエストがおこなわれず、完全なページ更新がおこなわれないことを確認します。 これにより、エンドユーザーにとって高速なSPAが実現し、AEMへの不要なリクエストが削減されます。

    ナビゲーションの実装

  5. 次の場所に直接移動して、ディープリンクを試してみます。http://localhost:4502/content/wknd-spa-angular/us/en/home/page-2.html. ブラウザーの戻るボタンが引き続き機能することを確認します。

おめでとうございます。

これで、SPA Editor SDKを使用してAEMページにマッピングすることで、SPAの複数のビューをサポートする方法を学びました。 動的ナビゲーションは、Angularルーティングを使用して実装され、Headerコンポーネントに追加されました。

GitHubで完成したコードをいつでも表示したり、ブランチAngular/navigation-routing-solutionに切り替えてコードをローカルでチェックアウトしたりできます。

次の手順

カスタムコンポーネントの作成 - AEM SPA Editorで使用するカスタムコンポーネントを作成する方法を説明します。JSONモデルを拡張してカスタムコンポーネントを設定するためのオーサーダイアログとSlingモデルの開発方法について説明します。

このページ