Hinzufügen von Navigation und Routing

Erfahren Sie, wie mehrere Ansichten in der SPA mithilfe von AEM Seiten und dem SPA Editor SDK unterstützt werden. Die dynamische Navigation wird mithilfe von Angular-Routen implementiert und zu einer vorhandenen Kopfzeilenkomponente hinzugefügt.

Ziele

  1. Machen Sie sich mit den SPA Routing-Optionen vertraut, die bei Verwendung des SPA-Editors verfügbar sind.
  2. Erfahren Sie, wie Sie mit Angular-Routing zwischen verschiedenen Ansichten der SPA navigieren können.
  3. Implementieren Sie eine dynamische Navigation, die von der AEM-Seitenhierarchie gesteuert wird.

Was Sie erstellen werden

Dieses Kapitel fügt ein Navigationsmenü zu einer vorhandenen Header-Komponente hinzu. Das Navigationsmenü wird von der AEM Seitenhierarchie gesteuert und verwendet das JSON-Modell, das von der Navigations-Kernkomponente bereitgestellt wird.

Implementierung der Navigation

Voraussetzungen

Überprüfen Sie die erforderlichen Tools und Anweisungen zum Einrichten einer lokalen Entwicklungsumgebung.

Code abrufen

  1. Laden Sie den Ausgangspunkt für dieses Tutorial über Git herunter:

    $ git clone git@github.com:adobe/aem-guides-wknd-spa.git
    $ cd aem-guides-wknd-spa
    $ git checkout Angular/navigation-routing-start
    
  2. Stellen Sie die Codebasis mithilfe von Maven in einer lokalen AEM-Instanz bereit:

    $ mvn clean install -PautoInstallSinglePackage
    

    Wenn Sie AEM 6.x verwenden, fügen Sie das Profil classic hinzu:

    $ mvn clean install -PautoInstallSinglePackage -Pclassic
    
  3. Installieren Sie das fertige Paket für die traditionelle Referenz-Site WKND. Die von WKND-Referenz-Site bereitgestellten Bilder werden auf der WKND-SPA wiederverwendet. Das Paket kann mit AEM Package Manager installiert werden.

    Package Manager install wknd.all

Sie können den fertigen Code immer auf GitHub anzeigen oder den Code lokal auschecken, indem Sie zu der Verzweigung Angular/navigation-routing-solution wechseln.

Aktualisierungen der Inspect HeaderComponent

In vorherigen Kapiteln wurde die Komponente HeaderComponent als reine Angular-Komponente hinzugefügt, die über app.component.html eingeschlossen ist. In diesem Kapitel wird die Komponente HeaderComponent aus der App entfernt und über den Vorlagen-Editor hinzugefügt. Dadurch können Benutzer das Navigationsmenü des HeaderComponent von AEM aus konfigurieren.

HINWEIS

Für die Codebasis wurden bereits mehrere CSS- und JavaScript-Aktualisierungen vorgenommen, um dieses Kapitel zu starten. Um sich auf Kernkonzepte zu konzentrieren, werden nicht alle der Codeänderungen besprochen. Sie können die vollständigen Änderungen hier anzeigen.

  1. Öffnen Sie in der IDE Ihrer Wahl das SPA Startprojekt für dieses Kapitel.

  2. Unterhalb des Moduls ui.frontend überprüfen Sie die Datei header.component.ts unter: ui.frontend/src/app/components/header/header.component.ts.

    Es wurden verschiedene Aktualisierungen vorgenommen, darunter das Hinzufügen von HeaderEditConfig und einem MapTo, um die Zuordnung der Komponente zu einer AEM Komponente wknd-spa-angular/components/header zu ermöglichen.

    /* 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);
    

    Beachten Sie die @Input() -Anmerkung für items. items enthält ein Array von Navigationsobjekten, die von AEM übergeben werden.

  3. Überprüfen Sie im Modul ui.apps die Komponentendefinition der AEM Header -Komponente: 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"/>
    

    Die AEM Header-Komponente übernimmt alle Funktionen der Navigations-Kernkomponente über die sling:resourceSuperType-Eigenschaft.

Hinzufügen der HeaderComponent zur SPA Vorlage

  1. Öffnen Sie einen Browser und melden Sie sich AEM http://localhost:4502/ an. Die Basis für den Startcode sollte bereits bereitgestellt werden.

  2. Navigieren Sie zur SPA Seitenvorlage: http://localhost:4502/editor.html/conf/wknd-spa-angular/settings/wcm/templates/spa-page-template/structure.html.

  3. Wählen Sie den äußersten Root Layout Container aus und klicken Sie auf das Symbol Richtlinie. Achten Sie darauf, dass nicht den Layout-Container nicht gesperrt für die Bearbeitung auswählt.

    Wählen Sie das Symbol für die Root Layout Container-Richtlinie aus

  4. Kopieren Sie die aktuelle Richtlinie und erstellen Sie eine neue Richtlinie mit dem Namen SPA Struktur:

    SPA

    Wählen Sie unter Zulässige Komponenten > Allgemein die Komponente Layout-Container aus.

    Wählen Sie unter Zulässige Komponenten > WKND SPA ANGULAR - STRUKTUR > die Komponente Header aus:

    Kopfzeilenkomponente auswählen

    Wählen Sie unter Zulässige Komponenten > WKND SPA ANGULAR - Content > die Komponenten Bild und Text aus. Es sollten vier Komponenten ausgewählt sein.

    Klicken Sie auf Fertig , um die Änderungen zu speichern.

  5. Aktualisieren Sie die Seite. Fügen Sie die Komponente Header oberhalb der nicht gesperrten Komponente Layout-Container hinzu:

    Header-Komponente zur Vorlage hinzufügen

  6. Wählen Sie die Komponente Header aus und klicken Sie auf das Symbol Richtlinie , um die Richtlinie zu bearbeiten.

    Auf Kopfzeilenrichtlinie klicken

  7. Erstellen Sie eine neue Richtlinie mit dem Richtlinientitel von "WKND SPA Header".

    Unter Properties:

    • Setzen Sie den Navigationsstamm auf /content/wknd-spa-angular/us/en.
    • Setzen Sie Stammebenen ausschließen auf 1.
    • Deaktivieren Sie Sammlung aller untergeordneten Seiten.
    • Setzen Sie die Navigationsstrukturtiefe auf 3.

    Kopfzeilenrichtlinie konfigurieren

    Dadurch werden die Navigations-2 Ebenen tief unter /content/wknd-spa-angular/us/en erfasst.

  8. Nachdem Sie Ihre Änderungen gespeichert haben, sollte das ausgefüllte Header als Teil der Vorlage angezeigt werden:

    Füllende Kopfzeilenkomponente

Untergeordnete Seiten erstellen

Als Nächstes erstellen Sie zusätzliche Seiten in AEM , die als verschiedene Ansichten in der SPA dienen. Wir werden auch die hierarchische Struktur des von AEM bereitgestellten JSON-Modells untersuchen.

  1. Navigieren Sie zur Konsole Sites: http://localhost:4502/sites.html/content/wknd-spa-angular/us/en/home. Wählen Sie die WKND SPA Angular-Homepage aus und klicken Sie auf Erstellen > Seite:

    Neue Seite erstellen

  2. Wählen Sie unter Vorlage SPA Seite aus. Geben Sie unter Properties "Page 1" für Title und "page-1" als Namen ein.

    anfängliche Seiteneigenschaften eingeben

    Klicken Sie auf Erstellen und klicken Sie im Popup-Dialogfeld auf Öffnen , um die Seite im AEM SPA Editor zu öffnen.

  3. Fügen Sie eine neue Komponente Text zum Haupt-Container Layout-Container hinzu. Bearbeiten Sie die Komponente und geben Sie den Text ein: "Seite 1" unter Verwendung des RTE und des Elements H1 (Sie müssen in den Vollbildmodus wechseln, um die Absatzelemente zu ändern)

    Beispielinhaltsseite 1

    Sie können zusätzliche Inhalte hinzufügen, wie z. B. ein Bild.

  4. Kehren Sie zur AEM Sites-Konsole zurück und wiederholen Sie die obigen Schritte. Erstellen Sie eine zweite Seite mit dem Namen "Seite 2" als Geschwister von Seite 1. Fügen Sie Seite 2 Inhalt hinzu, damit sie leicht identifiziert werden kann.

  5. Erstellen Sie abschließend eine dritte Seite, "Seite 3", aber als untergeordnetes Element von Seite 2. Nach Abschluss der Site-Hierarchie sollte wie folgt aussehen:

    Beispiel-Site-Hierarchie

  6. Öffnen Sie in einer neuen Registerkarte die von AEM bereitgestellte JSON-Modell-API: http://localhost:4502/content/wknd-spa-angular/us/en.model.json. Dieser JSON-Inhalt wird angefordert, wenn die SPA zum ersten Mal geladen wird. Die äußere Struktur sieht wie folgt aus:

    {
    "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": {}
        }
    }
    

    Unter :children sollte für jede der erstellten Seiten ein Eintrag angezeigt werden. Der Inhalt für alle Seiten befindet sich in dieser ersten JSON-Anfrage. Sobald das Navigations-Routing implementiert wurde, werden nachfolgende Ansichten des SPA schnell geladen, da der Inhalt bereits clientseitig verfügbar ist.

    Es ist nicht ratsam, ALL des Inhalts eines SPA in der ersten JSON-Anfrage zu laden, da dies das anfängliche Laden der Seite verlangsamen würde. Als Nächstes sehen wir, wie die Hierarchietiefe der Seiten erfasst wird.

  7. Navigieren Sie zur Vorlage SPA Stamm unter: http://localhost:4502/editor.html/conf/wknd-spa-angular/settings/wcm/templates/spa-app-template/structure.html.

    Klicken Sie auf das Menü Seiteneigenschaften > Seitenrichtlinie:

    Öffnen Sie die Seitenrichtlinie für SPA Stamm.

  8. Die Vorlage SPA Stamm verfügt über eine zusätzliche Registerkarte Hierarchische Struktur , um den erfassten JSON-Inhalt zu steuern. Die Strukturtiefe bestimmt, wie tief in der Site-Hierarchie untergeordnete Seiten unter root erfasst werden. Sie können auch das Feld Strukturmuster verwenden, um zusätzliche Seiten basierend auf einem regulären Ausdruck herauszufiltern.

    Aktualisieren Sie die Strukturtiefe auf "2":

    Aktualisierung der Strukturtiefe

    Klicken Sie auf Fertig , um die Änderungen an der Richtlinie zu speichern.

  9. Öffnen Sie das JSON-Modell http://localhost:4502/content/wknd-spa-angular/us/en.model.json erneut.

    {
    "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": {}
        }
    }
    

    Beachten Sie, dass der Pfad Seite 3 entfernt wurde: /content/wknd-spa-angular/us/en/home/page-2/page-3 vom ersten JSON-Modell aus.

    Später werden wir feststellen, wie das AEM SPA Editor SDK zusätzliche Inhalte dynamisch laden kann.

Implementieren der Navigation

Implementieren Sie anschließend das Navigationsmenü mit einem neuen NavigationComponent. Wir könnten den Code direkt in header.component.html hinzufügen. Es empfiehlt sich jedoch, große Komponenten zu vermeiden. Implementieren Sie stattdessen ein NavigationComponent , das später möglicherweise wiederverwendet werden könnte.

  1. Überprüfen Sie die JSON, die von der AEM Header-Komponente unter http://localhost:4502/content/wknd-spa-angular/us/en.model.json bereitgestellt wird:

    ...
    "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"
    

    Die hierarchische Natur der AEM ist in der JSON-Datei modelliert, die zum Ausfüllen eines Navigationsmenüs verwendet werden kann. Beachten Sie, dass die Header-Komponente alle Funktionen der Navigations-Kernkomponente übernimmt und der über die JSON angezeigte Inhalt automatisch der Angular-Anmerkung @Input zugeordnet wird.

  2. Öffnen Sie ein neues Terminal-Fenster und navigieren Sie zum Ordner ui.frontend des SPA-Projekts. Erstellen Sie ein neues NavigationComponent mit dem Angular CLI-Tool:

    $ 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. Erstellen Sie anschließend eine Klasse mit dem Namen NavigationLink mithilfe der Angular-CLI im neu erstellten components/navigation-Verzeichnis:

    $ 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. Kehren Sie zur IDE Ihrer Wahl zurück und öffnen Sie die Datei unter navigation-link.ts unter /src/app/components/navigation/navigation-link.ts.

    Datei "navigation-link.ts"öffnen

  5. Füllen Sie navigation-link.ts wie folgt:

    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);
            });
        }
    }
    

    Dies ist eine einfache Klasse zur Darstellung eines einzelnen Navigationslinks. Im Klassenkonstruktor erwarten wir, dass data das von AEM übergebene JSON-Objekt ist. Diese Klasse wird sowohl in NavigationComponent als auch in HeaderComponent verwendet, um die Navigationsstruktur einfach auszufüllen.

    Es wird keine Datenumwandlung durchgeführt. Diese Klasse wird hauptsächlich erstellt, um das JSON-Modell stark einzugeben. Beachten Sie, dass this.children als NavigationLink[] eingegeben wird und dass der Konstruktor rekursiv neue NavigationLink-Objekte für jedes der Elemente im children-Array erstellt. Beachten Sie, dass das JSON-Modell für Header hierarchisch ist.

  6. Öffnen Sie die Datei navigation-link.spec.ts. Dies ist die Testdatei für die Klasse NavigationLink . Aktualisieren Sie es mit folgenden Daten:

    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();
        });
    });
    

    Beachten Sie, dass const data demselben JSON-Modell folgt, das zuvor auf einen einzelnen Link überprüft wurde. Dies ist alles andere als ein robuster Komponententest, es sollte jedoch ausreichen, den Konstruktor von NavigationLink zu testen.

  7. Öffnen Sie die Datei navigation.component.ts. Aktualisieren Sie es mit folgenden Daten:

    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 erwartet einen object[] Namen, items der das JSON-Modell von AEM ist. Diese Klasse stellt eine einzelne Methode get navigationLinks() bereit, die ein Array von NavigationLink -Objekten zurückgibt.

  8. Öffnen Sie die Datei navigation.component.html und aktualisieren Sie sie wie folgt:

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

    Dadurch wird ein erster <ul>-Wert generiert und die get navigationLinks()-Methode von navigation.component.ts aufgerufen. Ein <ng-container> wird verwendet, um einen Aufruf an eine Vorlage mit dem Namen recursiveListTmpl durchzuführen und den navigationLinks als Variable mit dem Namen links zu übergeben.

    Fügen Sie als Nächstes recursiveListTmpl hinzu:

    <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>
    

    Hier wird der Rest des Renderings für den Navigationslink implementiert. Beachten Sie, dass die Variable link vom Typ NavigationLink ist und alle von dieser Klasse erstellten Methoden/Eigenschaften verfügbar sind. [routerLink] anstelle des normalen href Attributs verwendet. Auf diese Weise können wir Links zu bestimmten Routen im Programm erstellen, ohne dass die Seite vollständig aktualisiert wird.

    Der rekursive Teil der Navigation wird auch durch Erstellen eines weiteren <ul> implementiert, wenn das aktuelle link ein nicht leeres children-Array aufweist.

  9. Aktualisieren Sie navigation.component.spec.ts, um Unterstützung für RouterTestingModule hinzuzufügen:

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

    Das Hinzufügen von RouterTestingModule ist erforderlich, da die Komponente [routerLink] verwendet.

  10. Aktualisieren Sie navigation.component.scss, um einige grundlegende Stile zu NavigationComponent hinzuzufügen:

@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;
    }

}

Aktualisieren der Kopfzeilenkomponente

Nachdem NavigationComponent implementiert wurde, muss HeaderComponent aktualisiert werden, um darauf zu verweisen.

  1. Öffnen Sie ein Terminal und navigieren Sie zum Ordner ui.frontend im SPA Projekt. Starten Sie den webpack-Dev-Server:

    $ npm start
    
  2. Öffnen Sie eine Browser-Registerkarte und navigieren Sie zu http://localhost:4200/.

    Der webpack-Dev-Server sollte so konfiguriert werden, dass er das JSON-Modell von einer lokalen Instanz von AEM (ui.frontend/proxy.conf.json) proxyliert. Auf diese Weise können wir direkt mit den Inhalten vergleichen, die in AEM zuvor im Tutorial erstellt wurden.

    Funktionswechsel im Menü

    Die Funktion HeaderComponent ist derzeit bereits mit dem Menüumschalter implementiert. Fügen Sie als Nächstes die Navigationskomponente hinzu.

  3. Kehren Sie zur IDE Ihrer Wahl zurück und öffnen Sie die Datei header.component.ts unter ui.frontend/src/app/components/header/header.component.ts.

  4. Aktualisieren Sie die setHomePage()-Methode, um den hartcodierten String zu entfernen und die von der AEM übergebenen dynamischen Eigenschaften zu verwenden:

    /* 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;
        }
    }
    ...
    

    Eine neue Instanz von NavigationLink wird basierend auf items[0] erstellt, dem Stamm des JSON-Navigationsmodells, das von AEM übergeben wird. this.route.snapshot.data.path gibt den Pfad der aktuellen Angular-Route zurück. Mit diesem Wert wird bestimmt, ob die aktuelle Route die Homepage ist. this.homePageUrl wird verwendet, um den Ankerlink auf dem Logo zu füllen.

  5. Öffnen Sie header.component.html und ersetzen Sie den statischen Platzhalter für die Navigation durch einen Verweis auf die neu erstellte NavigationComponent:

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

    [items]=items übergibt die @Input() items von HeaderComponent an die NavigationComponent Stelle, an der die Navigation erstellt wird.

  6. Öffnen Sie header.component.spec.ts und fügen Sie eine Deklaration für NavigationComponent hinzu:

        /* 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();
        }));
    

    Da das NavigationComponent jetzt als Teil des HeaderComponent verwendet wird, muss es als Teil des Testbetts deklariert werden.

  7. Speichern Sie Änderungen an allen geöffneten Dateien und kehren Sie zum webpack-Dev-Server zurück: http://localhost:4200/

    Abgeschlossene Kopfzeilennavigation

    Öffnen Sie die Navigation, indem Sie auf den Menüumschalter klicken. Daraufhin sollten die ausgefüllten Navigationslinks angezeigt werden. Sie sollten zu verschiedenen Ansichten des SPA navigieren können.

Informationen zum SPA Routing

Nachdem die Navigation implementiert wurde, überprüfen Sie das Routing in AEM.

  1. Öffnen Sie in der IDE die Datei app-routing.module.ts unter ui.frontend/src/app.

    /* 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 {}
    

    Das routes: Routes = [];-Array definiert die Routen oder Navigationspfade zu Angular-Komponentenzuordnungen.

    AemPageMatcher ist ein benutzerdefinierter Angular-Router UrlMatcher, der mit allen Elementen übereinstimmt, die in AEM Angular-Anwendung "aussehen".

    PageComponent ist die Angular-Komponente, die eine Seite in AEM darstellt und die übereinstimmenden Routen aufrufen. Die PageComponent werden weiter geprüft.

    AemPageDataResolver, bereitgestellt vom AEM SPA Editor JS SDK, ist ein benutzerdefinierter Angular-Router- Resolver, der verwendet wird, um die Route-URL (den Pfad in AEM einschließlich der Erweiterung .html) in den Ressourcenpfad in AEM umzuwandeln, was dem Seitenpfad abzüglich der Erweiterung entspricht.

    Beispielsweise wandelt AemPageDataResolver die URL einer Route von content/wknd-spa-angular/us/en/home.html in den Pfad /content/wknd-spa-angular/us/en/home um. Damit wird der Seiteninhalt basierend auf dem Pfad in der JSON-Modell-API aufgelöst.

    AemPageRouteReuseStrategy, bereitgestellt vom AEM SPA Editor JS SDK, ist eine benutzerdefinierte 🔗 RouteReuseStrategy, die die Wiederverwendung der PageComponent über Routen hinweg verhindert. Andernfalls wird der Inhalt von Seite "A"beim Navigieren zu Seite "B"angezeigt.

  2. Öffnen Sie die Datei page.component.ts unter ui.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];
            });
        }
    }
    

    Der PageComponent ist erforderlich, um die von AEM abgerufene JSON zu verarbeiten, und wird als Angular-Komponente zum Rendern der Routen verwendet.

    ActivatedRoute, das vom Angular-Router-Modul bereitgestellt wird, enthält den Status, der angibt, welcher JSON-Inhalt AEM Seite in diese Angular-Seiten-Komponenteninstanz geladen werden soll.

    ModelManagerService, ruft die JSON-Daten basierend auf der Route ab und ordnet die Daten Klassenvariablen zu path, items, itemsOrder. Diese werden dann an AEMPageComponent übergeben.

  3. Öffnen Sie die Datei page.component.html unter ui.frontend/src/app/components/page/

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

    aem-page enthält die AEMPageComponent. Die Variablen path, items und itemsOrder werden an AEMPageComponent übergeben. Das AemPageComponent, das über die JavaScript-SDKs des SPA-Editors bereitgestellt wird, iteriert diese Daten und instanziiert Angular-Komponenten dynamisch basierend auf den JSON-Daten, wie im Tutorial Komponenten zuordnen dargestellt.

    Das PageComponent ist eigentlich nur ein Proxy für das AEMPageComponent und es ist das AEMPageComponent, das den Großteil der schweren Anhebung durchführt, um das JSON-Modell korrekt den Angular-Komponenten zuzuordnen.

Inspect SPA Routing in AEM

  1. Öffnen Sie ein Terminal und stoppen Sie den webpack-Dev-Server, falls er gestartet wurde. Navigieren Sie zum Stammverzeichnis des Projekts und stellen Sie das Projekt mithilfe Ihrer Maven-Fähigkeiten AEM bereit:

    $ cd aem-guides-wknd-spa
    $ mvn clean install -PautoInstallSinglePackage
    
    VORSICHT

    Für das Angular-Projekt sind einige sehr strenge Verknüpfungsregeln aktiviert. Wenn der Maven-Build fehlschlägt, überprüfen Sie den Fehler und suchen Sie nach Lint-Fehlern, die in den aufgelisteten Dateien gefunden werden.. Korrigieren Sie alle vom Cluster gefundenen Probleme und führen Sie den Maven-Befehl erneut aus.

  2. Navigieren Sie zur SPA Homepage in AEM: http://localhost:4502/content/wknd-spa-angular/us/en/home.html und öffnen Sie die Entwicklertools Ihres Browsers. Die folgenden Screenshots werden aus dem Google Chrome-Browser erfasst.

    Aktualisieren Sie die Seite und Sie sollten eine XHR-Anfrage an /content/wknd-spa-angular/us/en.model.json sehen, die der SPA Stamm ist. Beachten Sie, dass nur drei untergeordnete Seiten enthalten sind, basierend auf der Hierarchietiefenkonfiguration der SPA-Stammvorlage, die zuvor im Tutorial vorgenommen wurde. Dies umfasst nicht Seite 3.

    Anfängliche JSON-Anfrage - SPA Stamm

  3. Navigieren Sie bei geöffneten Entwicklertools zu Seite 3:

    Seite 3 Navigieren

    Beachten Sie, dass eine neue XHR-Anfrage an Folgendes gesendet wird: /content/wknd-spa-angular/us/en/home/page-2/page-3.model.json

    Seite drei XHR-Anfrage

    Der AEM Model Manager weiß, dass der JSON-Inhalt von Seite 3 nicht verfügbar ist, und Trigger automatisch die zusätzliche XHR-Anforderung.

  4. Fahren Sie mit den verschiedenen Navigationslinks mit dem SPA fort. Beachten Sie, dass keine zusätzlichen XHR-Anforderungen gestellt werden und keine vollständigen Seitenaktualisierungen stattfinden. Dadurch wird der SPA für den Endbenutzer schnell und unnötige Anforderungen werden an AEM reduziert.

    Implementierung der Navigation

  5. Experimentieren Sie mit Deep-Links, indem Sie direkt zu folgenden Elementen navigieren: http://localhost:4502/content/wknd-spa-angular/us/en/home/page-2.html. Beachten Sie, dass die Zurück-Schaltfläche des Browsers weiterhin funktioniert.

Herzlichen Glückwunsch!

Herzlichen Glückwunsch! Sie haben erfahren, wie mehrere Ansichten im SPA durch die Zuordnung zu AEM Seiten mit dem SPA Editor SDK unterstützt werden können. Die dynamische Navigation wurde mithilfe des Angular-Routing implementiert und der Komponente Header hinzugefügt.

Sie können den fertigen Code immer auf GitHub anzeigen oder den Code lokal auschecken, indem Sie zu der Verzweigung Angular/navigation-routing-solution wechseln.

Nächste Schritte

Erstellen einer benutzerdefinierten Komponente - Erfahren Sie, wie Sie eine benutzerdefinierte Komponente erstellen, die mit dem AEM SPA Editor verwendet werden kann. Erfahren Sie, wie Sie Bearbeitungsdialogfelder und Sling-Modelle entwickeln, um das JSON-Modell zu erweitern und eine benutzerdefinierte Komponente zu füllen.

Auf dieser Seite