Hinzufügen von Navigation und Routing navigation-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 Header-Komponente hinzugefügt.
Ziel
- Machen Sie sich mit den SPA-Modell-Routing-Optionen vertraut, die bei Verwendung des SPA-Editors verfügbar sind.
- Lernen Sie die Verwendung von Angular-Routing, um zwischen verschiedenen Ansichten der SPA zu navigieren.
- Implementieren Sie eine dynamische Navigation, die von der AEM-Seitenhierarchie gesteuert wird.
Was Sie erstellen werden
Dieses Kapitel fügt ein Navigationsmenü zu einer bestehenden Header
-Komponente hinzu. Das Navigationsmenü wird von der AEM-Seitenhierarchie gesteuert und verwendet das JSON-Modell, das von der Navigations-Kernkomponente bereitgestellt wird.
Voraussetzungen
Vergegenwärtigen Sie sich die erforderlichen Tools und Anweisungen zum Einrichten einer lokalen Entwicklungsumgebung.
Abrufen des Codes
-
Laden Sie den Ausgangspunkt für dieses Tutorial über Git herunter:
code language-shell $ git clone git@github.com:adobe/aem-guides-wknd-spa.git $ cd aem-guides-wknd-spa $ git checkout Angular/navigation-routing-start
-
Stellen Sie die Code-Basis mithilfe von Maven in einer lokalen AEM-Instanz bereit:
code language-shell $ mvn clean install -PautoInstallSinglePackage
Wenn Sie AEM 6.x verwenden, fügen Sie das Profil
classic
hinzu:code language-shell $ mvn clean install -PautoInstallSinglePackage -Pclassic
-
Installieren Sie das fertige Paket für die herkömmliche WKND-Referenz-Website. Die Bilder von der WKND-Referenz-Website werden auf der WKND-SPA wiederverwendet. Das Paket kann mit AEM Package Manager installiert werden.
Sie können den fertigen Code jederzeit auf GitHub ansehen oder den Code lokal auschecken, indem Sie zur Verzweigung Angular/navigation-routing-solution
wechseln.
Prüfen der HeaderComponent-Updates inspect-header
In vorherigen Kapiteln wurde die HeaderComponent
-Komponente als reine Angular-Komponente hinzugefügt, die über app.component.html
eingebunden wurde. In diesem Kapitel wird die HeaderComponent
-Komponente aus der App entfernt und über den Vorlageneditor hinzugefügt. Dies ermöglicht es den Benutzenden, das Navigationsmenü der HeaderComponent
von AEM aus zu konfigurieren.
-
Öffnen Sie in der IDE Ihrer Wahl das SPA-Startprojekt für dieses Kapitel.
-
Überprüfen Sie unter dem
ui.frontend
-Modul die Dateiheader.component.ts
unterui.frontend/src/app/components/header/header.component.ts
.Es wurden mehrere Aktualisierungen vorgenommen, darunter das Hinzufügen einer
HeaderEditConfig
undMapTo
, damit die Komponente einemwknd-spa-angular/components/header
einer AEM-Komponente zugeordnet werden kann.code language-js /* 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 Anmerkung
@Input()
füritems
.items
enthält ein Array von Navigationsobjekten, die von AEM übergeben werden. -
Prüfen Sie im
ui.apps
-Modul die Komponentendefinition der AEM-Header
-Komponente:ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/header/.content.xml
:code language-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 die gesamte Funktionalität der Navigations-Kernkomponente über diesling:resourceSuperType
-Eigenschaft.
Hinzufügen der HeaderComponent zur SPA-Vorlage add-header-template
-
Öffnen Sie einen Browser und melden Sie sich bei AEM an, http://localhost:4502/. Die Code-Basis für den Start sollte bereits bereitgestellt sein.
-
Navigieren Sie zur SPA Seitenvorlage: http://localhost:4502/editor.html/conf/wknd-spa-angular/settings/wcm/templates/spa-page-template/structure.html.
-
Wählen Sie den äußersten Stamm-Layout-Container aus und klicken Sie auf das Symbol Richtlinie. Achten Sie darauf, dass Sie nicht den Layout-Container auswählen, der für das Authoring entsperrt ist.
-
Kopieren Sie die aktuelle Richtlinie und erstellen Sie eine neue Richtlinie mit dem Namen SPA-Struktur:
Wählen Sie unter Zugelassene Komponenten > Allgemein die Layout-Container-Komponente.
Wählen Sie unter Zugelassene Komponenten > WKND SPA ANGULAR – STRUKTUR die Header-Komponente:
Wählen Sie unter Zugelassene Komponenten > WKND SPA ANGULAR – Inhalt die Bild- und Text-Komponenten. Es sollten insgesamt vier Komponenten ausgewählt sein.
Klicken Sie auf Fertig, um die Änderungen zu speichern.
-
Aktualisieren Sie die Seite. Fügen Sie die Header-Komponente über dem nicht gesperrten Layout-Container hinzu:
-
Wählen Sie die Header-Komponente und klicken Sie auf das Richtlinien-Symbol zum Bearbeiten der Richtlinie.
-
Erstellen Sie eine neue Richtlinie mit Richtliniennamen „WKND SPA-Header“.
Unter den Eigenschaften:
- Legen Sie den Navigationsstamm auf
/content/wknd-spa-angular/us/en
fest. - Legen Sie für Stammebenen ausschließen den Wert 1 fest.
- Deaktivieren Sie Alle untergeordneten Seiten erfassen.
- Setzen Sie die Navigationsstrukturtiefe auf 3.
Dadurch wird die Navigation 2 Ebenen unterhalb von
/content/wknd-spa-angular/us/en
erfasst. - Legen Sie den Navigationsstamm auf
-
Nach dem Speichern der Änderungen sollten Sie den aufgefüllten
Header
als Teil der Vorlage sehen:
Erstellen untergeordneter Seiten
Als Nächstes erstellen wir 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.
-
Navigieren Sie zur Sites-Konsole: http://localhost:4502/sites.html/content/wknd-spa-angular/us/en/home. Wählen Sie die WKND SPA Angular-Homepage und klicken Sie auf Erstellen > Seite:
-
Wählen Sie unter Vorlage die Option SPA-Seite aus. Geben Sie unter Eigenschaften „Seite 1“ für den Titel und „Seite 1“ als Namen ein.
Klicken Sie auf Erstellen und dann im Dialogfeld-Popup auf Öffnen, um die Seite im AEM-SPA-Editor zu öffnen.
-
Fügen Sie eine neue Text-Komponente zum Haupt-Layout-Container hinzu. Bearbeiten Sie die Komponente und geben Sie folgenden Text ein: „Seite 1“ unter Verwendung des RTE und des Elements H1 (Sie müssen in den Vollbildmodus wechseln, um die Absatzelemente zu ändern)
Sie können gerne zusätzliche Inhalte hinzufügen, z. B. ein Bild.
-
Kehren Sie zur AEM Sites-Konsole zurück und wiederholen Sie die obigen Schritte, indem Sie eine zweite Seite mit dem Namen „Seite 2“ als gleichgeordnet zu Seite 1 erstellen. Fügen Sie Inhalt auf Seite 2 ein, sodass sie leicht zu erkennen ist.
-
Erstellen Sie abschließend eine dritte Seite, „Seite 3“, diese jedoch als untergeordnet zu Seite 2. Danach sollte die Website-Hierarchie wie folgt aussehen:
-
Ö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:
code language-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": {}, "/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 ist in dieser ersten JSON-Anfrage enthalten. Sobald das Navigations-Routing implementiert ist, werden nachfolgende Ansichten der SPA schnell geladen, da der Inhalt bereits Client-seitig verfügbar ist.Es ist nicht ratsam, den GESAMTEN Inhalt einer 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.
-
Navigieren Sie zur SPA-Stamm-Vorlage 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:
-
Die SPA-Stammvorlage weist die zusätzliche Registerkarte Hierarchische Struktur für den erfassten JSON-Inhalt auf. Die Strukturtiefe bestimmt, wie tief in der Website-Hierarchie untergeordnete Seiten unterhalb des Stamms erfasst werden. Sie können auch das Feld Strukturmuster zum Filtern zusätzlicher Seiten basierend auf einem regulären Ausdruck verwenden.
Aktualisieren Sie die Strukturtiefe auf „2“:
Klicken Sie auf Fertig, um die Änderungen an der Richtlinie zu speichern.
-
Öffnen Sie erneut das JSON-Modell http://localhost:4502/content/wknd-spa-angular/us/en.model.json.
code language-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": {} } }
Beachten Sie, dass der Pfad von Seite 3 entfernt wurde:
/content/wknd-spa-angular/us/en/home/page-2/page-3
vom ersten JSON-Modell.Später werden wir sehen, wie das AEM SPA Editor SDK zusätzliche Inhalte dynamisch laden kann.
Implementieren der Navigation
Implementieren Sie anschließend das Navigationsmenü mit einer neuen NavigationComponent
. Wir könnten den Code direkt in header.component.html
hinzufügen, doch es empfiehlt sich, große Komponenten zu vermeiden. Implementieren Sie stattdessen eine NavigationComponent
, die später möglicherweise wiederverwendet werden kann.
-
Ü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:code language-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"
Die hierarchische Natur von AEM-Seiten ist in der JSON-Datei modelliert, die zum Ausfüllen eines Navigationsmenüs verwendet werden kann. Erinnern Sie sich daran, dass die
Header
-Komponente die gesamte Funktionalität der Navigations-Kernkomponente übernimmt und der über die JSON angezeigte Inhalt automatisch der@Input
-Notierung von Angular zugeordnet wird. -
Öffnen Sie ein neues Terminal-Fenster und navigieren Sie zum Ordner
ui.frontend
des SPA-Projekts. Erstellen Sie eine neueNavigationComponent
mit dem Angular CLI-Tool:code language-shell $ 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)
-
Erstellen Sie als Nächstes eine Klasse mit dem Namen
NavigationLink
mithilfe der Angular-CLI im neu erstellten Verzeichniscomponents/navigation
:code language-shell $ 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)
-
Kehren Sie zur IDE Ihrer Wahl zurück und öffnen Sie die Datei auf
navigation-link.ts
unter/src/app/components/navigation/navigation-link.ts
. -
Füllen Sie
navigation-link.ts
wie folgt:code language-js 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 in den beiden KomponentenNavigationComponent
undHeaderComponent
verwendet, um die Navigationsstruktur einfach zu befüllen.Es wird keine Datenumwandlung durchgeführt. Diese Klasse wird hauptsächlich erstellt, um das JSON-Modell stark zu typisieren. Beachten Sie, dass
this.children
alsNavigationLink[]
typisiert wird und dass der Konstruktor rekursiv neueNavigationLink
-Objekte für jedes der Elemente imchildren
-Array erstellt. Erinnern Sie sich daran, dass das JSON-Modell fürHeader
hierarchisch ist. -
Öffnen Sie die Datei
navigation-link.spec.ts
. Dies ist die Testdatei für die KlasseNavigationLink
. Aktualisieren Sie sie wie folgt:code language-js 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, doch es sollte ausreichen, um den Konstruktor vonNavigationLink
zu testen. -
Öffnen Sie die Datei
navigation.component.ts
. Aktualisieren Sie sie wie folgt:code language-js 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 einobject[]
namensitems
, welches das JSON-Modell aus AEM ist. Diese Klasse stellt eine Einzelmethodeget navigationLinks()
bereit, die ein Array vonNavigationLink
-Objekten zurückgibt. -
Öffnen Sie die Datei
navigation.component.html
und aktualisieren Sie sie wie folgt:code language-html <ul *ngIf="navigationLinks && navigationLinks.length > 0" class="navigation__group"> <ng-container *ngTemplateOutlet="recursiveListTmpl; context:{ links: navigationLinks }"></ng-container> </ul>
Dadurch wird ein erster
<ul>
generiert und die Methodeget navigationLinks()
vonnavigation.component.ts
abgerufen. Ein<ng-container>
wird verwendet, um eine Vorlage mit dem NamenrecursiveListTmpl
abzurufen, und er übergibt ihr dienavigationLinks
als eine Variable namenslinks
.Fügen Sie als Nächstes das
recursiveListTmpl
hinzu:code language-html <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 Navigations-Link implementiert. Beachten Sie, dass die Variable
link
vom TypNavigationLink
ist und alle von dieser Klasse erstellten Methoden/Eigenschaften verfügbar sind.[routerLink]
wird anstelle des normalenhref
-Attributs verwendet. Auf diese Weise können wir Links zu bestimmten Routen in der App erstellen, ohne dass die Seite vollständig aktualisiert wird.Der rekursive Teil der Navigation wird ebenfalls implementiert, indem ein anderer
<ul>
erstellt wird, wenn der aktuellelink
ein nicht-leereschildren
-Array besitzt. -
Aktualisieren Sie
navigation.component.spec.ts
, um Unterstützung fürRouterTestingModule
hinzuzufügen:code language-diff ... + import { RouterTestingModule } from '@angular/router/testing'; ... beforeEach(async(() => { TestBed.configureTestingModule({ + imports: [ RouterTestingModule ], declarations: [ NavigationComponent ] }) .compileComponents(); })); ...
Das Hinzufügen des
RouterTestingModule
ist erforderlich, da die Komponente[routerLink]
verwendet. -
Aktualisieren Sie
navigation.component.scss
, um einige grundlegende Stile zurNavigationComponent
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 Header-Komponente
Nun, da NavigationComponent
implementiert worden ist, muss HeaderComponent
aktualisiert werden, um darauf zu verweisen.
-
Öffnen Sie ein Terminal und navigieren Sie zum Ordner
ui.frontend
im SPA-Projekt. Starten Sie den Webpack-Dev-Server:code language-shell $ npm start
-
Öffnen Sie im Browser eine Registerkarte und navigieren Sie zu http://localhost:4200/.
Der Webpack-Dev-Server sollte so konfiguriert sein, dass eine lokale Instanz von AEM (
ui.frontend/proxy.conf.json
) als Proxy für das JSON-Modell fungiert. Auf diese Weise können wir Code direkt anhand der Inhalte erstellen, die zuvor im Tutorial in AEM erstellt wurden.Für die
HeaderComponent
ist die Menüumschalter-Funktion bereits implementiert. Fügen Sie als Nächstes die Navigationskomponente hinzu. -
Kehren Sie zur IDE Ihrer Wahl zurück und öffnen Sie die Datei
header.component.ts
unterui.frontend/src/app/components/header/header.component.ts
. -
Aktualisieren Sie die Methode
setHomePage()
, um die hart-codierte Zeichenfolge zu entfernen und die von der AEM-Komponente übergebenen dynamischen Eigenschaften zu verwenden:code language-js /* 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 aufitems[0]
erstellt, dem Stamm des JSON-Navigationsmodells, das von AEM übergeben wurde.this.route.snapshot.data.path
gibt den Pfad der aktuellen Angular-Route zurück. Mit diesem Wert wird bestimmt, ob die aktuelle Route die Startseite ist.this.homePageUrl
wird verwendet, um den Anker-Link auf dem Logo einzufügen. -
Öffnen Sie
header.component.html
und ersetzen Sie den statischen Platzhalter für die Navigation durch einen Verweis auf die neu erstellteNavigationComponent
:code language-diff <div class="header-navigation"> <div class="navigation"> - Navigation Placeholder + <app-navigation [items]="items"></app-navigation> </div> </div>
Das Attribut
[items]=items
übergibt@Input() items
von derHeaderComponent
an dieNavigationComponent
, wo es die Navigation ausbaut. -
Öffnen Sie
header.component.spec.ts
und fügen Sie eine Deklaration für dieNavigationComponent
hinzu:code language-diff /* 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 die
NavigationComponent
jetzt als Teil derHeaderComponent
verwendet wird, muss sie als Teil der Testumgebung deklariert werden. -
Speichern Sie Änderungen an allen geöffneten Dateien und kehren Sie zurück zum Webpack-Dev-Server: http://localhost:4200/
Öffnen Sie die Navigation, indem Sie auf den Menüumschalter klicken. Daraufhin sollten die ausgefüllten Navigations-Links angezeigt werden. Sie sollten zu verschiedenen Ansichten der SPA navigieren können.
Verstehen des SPA-Routings
Nachdem die Navigation implementiert wurde, überprüfen Sie das Routing in AEM.
-
Öffnen Sie in der IDE die Datei
app-routing.module.ts
unterui.frontend/src/app
.code language-js /* 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-Komponenten-Zuordnungen.AemPageMatcher
ist ein benutzerdefinierter Angular-Router UrlMatcher, der alles als Übereinstimmung zählt, was wie eine Seite in AEM, die Teil dieser Angular-Anwendung ist, „aussieht“.PageComponent
ist die Angular-Komponente, die eine Seite in AEM darstellt und zum Rendern der übereinstimmenden Routen verwendet wird. DiePageComponent
wird später im Tutorial behandelt.AemPageDataResolver
, bereitgestellt vom AEM SPA Editor JS SDK, ist ein benutzerdefinierter Angular Router-Resolver, der verwendet wird, um die Routen-URL (den Pfad in AEM einschließlich der Erweiterung .html) in den Ressourcenpfad in AEM umzuwandeln, welcher dem Seitenpfad ohne die Erweiterung entspricht.Beispiel: Der
AemPageDataResolver
transformiert die URL einer Route voncontent/wknd-spa-angular/us/en/home.html
in einen Pfad von/content/wknd-spa-angular/us/en/home
. 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 derPageComponent
über Routen hinweg verhindert. Andernfalls wird beim Navigieren zur Seite „B“ möglicherweise Inhalt von Seite „A“ angezeigt. -
Öffnen Sie die Datei
page.component.ts
unterui.frontend/src/app/components/page/
.code language-js ... 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]; }); } }
Die
PageComponent
ist erforderlich, um die von AEM abgerufene JSON zu verarbeiten, und wird als Angular-Komponente zum Rendern der Routen verwendet.ActivatedRoute
, bereitgestellt vom Angular-Router-Modul, enthält den Status, der angibt, welcher JSON-Inhalt einer AEM Seite in diese Instanz einer Angular-Seitenkomponente geladen werden soll.ModelManagerService
ruft die JSON-Daten basierend auf der Route ab und ordnet die Daten den Klassenvariablenpath
,items
unditemsOrder
zu. Diese werden dann an die AEMPageComponent weitergegeben. -
Öffnen Sie die Datei
page.component.html
unterui.frontend/src/app/components/page/
code language-html <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 Variablenpath
,items
unditemsOrder
werden an dieAEMPageComponent
weitergegeben. DieAemPageComponent
, die über die SPA-Editor-JavaScript-SDKs bereitgestellt wird, durchläuft diese Daten und instanziiert Angular-Komponenten dynamisch basierend auf den JSON-Daten, wie im Tutorial zum Zuordnen von Komponenten zu sehen ist.Die
PageComponent
ist in Wirklichkeit nur ein Proxy für dieAEMPageComponent
, und es ist dieAEMPageComponent
, die den Großteil der Arbeit leistet, um das JSON-Modell korrekt den Angular-Komponenten zuzuordnen.
Überprüfen des SPA-Routings in AEM
-
Ö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:
code language-shell $ cd aem-guides-wknd-spa $ mvn clean install -PautoInstallSinglePackage
note caution CAUTION 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 gefundenen Lint-Fehlern in den aufgelisteten Dateien.. Korrigieren Sie alle vom Linter gefundenen Probleme und führen Sie den Maven-Befehl erneut aus. -
Navigieren Sie zur SPA-Homepage in AEM, http://localhost:4502/content/wknd-spa-angular/us/en/home.html, und öffnen Sie die Entwickler-Tools Ihres Browsers. Die folgenden Screenshots stammen vom Google Chrome-Browser.
Aktualisieren Sie die Seite. Sie sollten jetzt eine XHR-Anfrage an
/content/wknd-spa-angular/us/en.model.json
sehen, den SPA-Stamm. Beachten Sie, dass nur drei untergeordnete Seiten enthalten sind. Dies basiert auf der Hierarchietiefenkonfiguration der SPA-Stammvorlage, die zuvor im Tutorial vorgenommen wurde. Dies umfasst nicht Seite 3. -
Navigieren Sie bei geöffneten Entwickler-Tools zu Seite 3:
Beachten Sie, dass eine neue XHR-Anfrage an
/content/wknd-spa-angular/us/en/home/page-2/page-3.model.json
gesendet wirdDer AEM-Modell-Manager versteht, dass der JSON-Inhalt für Seite 3 nicht verfügbar ist und triggert automatisch die zusätzliche XHR-Anfrage.
-
Fahren Sie mit dem Navigieren der SPA durch Verwenden der verschiedenen Navigations-Links fort. Beachten Sie, dass keine zusätzlichen XHR-Anfragen erfolgen und keine vollständigen Seitenaktualisierungen stattfinden. Dadurch wird die SPA für die Endbenutzenden schneller, und die Zahl der unnötigen Anfragen zurück an AEM wird reduziert.
-
Experimentieren Sie mit Deep-Links, indem Sie direkt zu http://localhost:4502/content/wknd-spa-angular/us/en/home/page-2.html navigieren. Beachten Sie, dass der Zurück-Button des Browsers weiterhin funktioniert.
Herzlichen Glückwunsch! congratulations
Herzlichen Glückwunsch! Sie wissen jetzt, wie mehrere Ansichten in der SPA durch die Zuordnung zu AEM-Seiten mit dem SPA Editor SDK unterstützt werden können. Die dynamische Navigation wurde durch Verwenden des Angular-Routings implementiert und zur Header
-Komponente hinzugefügt.
Sie können den fertigen Code jederzeit auf GitHub ansehen oder den Code lokal auschecken, indem Sie zur Verzweigung Angular/navigation-routing-solution
wechseln.
Nächste Schritte next-steps
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 Autorendialogfelder und Sling-Modelle entwickeln, um das JSON-Modell zu erweitern und eine benutzerdefinierte Komponente zu füllen.