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.
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.
Vergegenwärtigen Sie sich die erforderlichen Tools und Anweisungen zum Einrichten einer lokalen Entwicklungsumgebung.
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
Stellen Sie die Code-Basis 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
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.
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.
Für die Code-Basis wurden am Anfang dieses Kapitels bereits mehrere CSS- und JavaScript-Aktualisierungen vorgenommen. Um sich auf die Kernkonzepte zu konzentrieren, werden nicht alle der Code-Änderungen erklärt. Sie können die vollständigen Änderungen hier einsehen.
Öffnen Sie in der IDE Ihrer Wahl das SPA-Startprojekt für dieses Kapitel.
Überprüfen Sie unter dem ui.frontend
-Modul die Datei header.component.ts
unter ui.frontend/src/app/components/header/header.component.ts
.
Es wurden mehrere Aktualisierungen vorgenommen, darunter das Hinzufügen einer HeaderEditConfig
und MapTo
, damit die Komponente einem wknd-spa-angular/components/header
einer AEM-Komponente zugeordnet werden kann.
/* 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ür items
. 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
:
<?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 die sling:resourceSuperType
-Eigenschaft.
Ö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, nicht den Layout-Container zu wä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:
/content/wknd-spa-angular/us/en
fest.Dadurch wird die Navigation 2 Ebenen unterhalb von /content/wknd-spa-angular/us/en
erfasst.
Nach dem Speichern der Änderungen sollten Sie den aufgefüllten Header
als Teil der Vorlage sehen:
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 im Pop-up-Dialogfeld 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:
{
"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-Stamm-Vorlage hat ein zusätzliche Registerkarte Hierarchische Struktur, um den erfassten JSON-Inhalt zu kontrollieren. Die Strukturtiefe bestimmt, wie tief in der Site-Hierarchie untergeordnete Seiten unterhalb der 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.
{
"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 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:
...
"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 neue 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)
Erstellen Sie als Nächstes eine Klasse mit dem Namen NavigationLink
mithilfe der Angular-CLI im neu erstellten Verzeichnis components/navigation
:
$ 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:
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 Komponenten NavigationComponent
und HeaderComponent
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
als NavigationLink[]
typisiert wird und dass der Konstruktor rekursiv neue NavigationLink
-Objekte für jedes der Elemente im children
-Array erstellt. Erinnern Sie sich daran, dass das JSON-Modell für Header
hierarchisch ist.
Öffnen Sie die Datei navigation-link.spec.ts
. Dies ist die Testdatei für die Klasse NavigationLink
. Aktualisieren Sie sie wie folgt:
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 von NavigationLink
zu testen.
Öffnen Sie die Datei navigation.component.ts
. Aktualisieren Sie sie wie folgt:
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 ein object[]
namens items
, welches das JSON-Modell aus AEM ist. Diese Klasse stellt eine Einzelmethode get navigationLinks()
bereit, die ein Array von NavigationLink
-Objekten zurückgibt.
Ö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>
generiert und die Methode get navigationLinks()
von navigation.component.ts
abgerufen. Ein <ng-container>
wird verwendet, um eine Vorlage mit dem Namen recursiveListTmpl
abzurufen, und er übergibt ihr die navigationLinks
als eine Variable namens links
.
Fügen Sie als Nächstes das 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 Navigations-Link implementiert. Beachten Sie, dass die Variable link
vom Typ NavigationLink
ist und alle von dieser Klasse erstellten Methoden/Eigenschaften verfügbar sind. [routerLink]
wird anstelle des normalen href
-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 aktuelle link
ein nicht-leeres children
-Array besitzt.
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 des RouterTestingModule
ist erforderlich, da die Komponente [routerLink]
verwendet.
Aktualisieren Sie navigation.component.scss
, um einige grundlegende Stile zur 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;
}
}
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:
$ 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
unter ui.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:
/* 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 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 erstellte NavigationComponent
:
<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 der HeaderComponent
an die NavigationComponent
, wo es die Navigation ausbaut.
Öffnen Sie header.component.spec.ts
und fügen Sie eine Deklaration für die 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 die NavigationComponent
jetzt als Teil der HeaderComponent
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.
Nachdem die Navigation implementiert wurde, überprüfen Sie das Routing in AEM.
Ö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-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. Die PageComponent
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 von content/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 der PageComponent
ü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
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];
});
}
}
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 Klassenvariablen path
, items
und itemsOrder
zu. Diese werden dann an die AEMPageComponent weitergegeben.
Ö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 die AEMPageComponent
weitergegeben. Die AemPageComponent
, 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 die AEMPageComponent
, und es ist die AEMPageComponent
, die den Großteil der Arbeit leistet, um das JSON-Modell korrekt den Angular-Komponenten zuzuordnen.
Ö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
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 wird
Der 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! 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.
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.