Erfahren Sie, wie Sie eine vorhandene Kernkomponente erweitern, um sie mit dem AEM-SPA-Editor zu verwenden. Das Verständnis, wie eine vorhandene Komponente erweitert wird, liefert eine wirkungsvolle Methode, um die Funktionen einer AEM-SPA-Editor-Implementierung anzupassen und zu erweitern.
sling:resourceSuperType
.In diesem Kapitel wird eine neue Card
-Komponente erstellt. Die Card
-Komponente erweitert die Bild-Kernkomponente und fügt zusätzliche Inhaltsfelder wie einen Titel und eine Aktionsaufruf-Schaltfläche hinzu, um die Rolle eines Teasers für andere Inhalte in der SPA auszuführen.
Bei einer echten Implementierung kann es je nach Projektanforderungen sinnvoller sein, einfach die Teaser-Komponente zu verwenden und nicht die Bild-Kernkomponente zu erweitern, um eine Card
-Komponente zu erstellen. Es wird immer empfohlen, Kernkomponenten direkt zu verwenden, soweit möglich.
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/extend-component-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 von der WKND-Referenz-Website bereitgestellten Bilder werden in 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/extend-component-solution
wechseln.
Eine erste Kartenkomponente wurde durch den Code zu Beginn des Kapitels bereitgestellt. Überprüfen Sie den Ausgangspunkt für die Kartenimplementierung.
Öffnen Sie das ui.apps
-Modul in der IDE Ihrer Wahl.
Navigieren Sie zu ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/card
und zeigen Sie die Datei .content.xml
an.
<?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="Card"
sling:resourceSuperType="wknd-spa-angular/components/image"
componentGroup="WKND SPA Angular - Content"/>
Die Eigenschaft sling:resourceSuperType
verweist auf wknd-spa-angular/components/image
und gibt an, dass die Card
-Komponente die Funktionalität von der WKND-SPA-Bildkomponente erbt.
Überprüfen Sie die Datei ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/image/.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="Image"
sling:resourceSuperType="core/wcm/components/image/v2/image"
componentGroup="WKND SPA Angular - Content"/>
Beachten Sie, dass sling:resourceSuperType
auf core/wcm/components/image/v2/image
verweist. Dies bedeutet, dass die WKND SPA-Bildkomponente die Funktionalität vom Kernkomponentenbild übernimmt.
Die Vererbung von Sling-Ressourcen, auch bekannt als Proxy-Muster, ist ein leistungsfähiges Design-Muster, das es untergeordneten Komponenten ermöglicht, Funktionalitäten zu erben und das Verhalten bei Bedarf zu erweitern oder zu überschreiben. Die Sling-Vererbung unterstützt mehrere Vererbungsebenen, sodass die neue Card
-Komponente letztendlich die Funktionalität des Kernkomponentenbilds erbt.
Viele Entwicklungs-Teams streben danach, D.R.Y. zu sein, sich also nicht selbst zu wiederholen. Die Sling-Vererbung ermöglicht dies mit AEM.
Öffnen Sie die Datei _cq_dialog/.content.xml
unter dem Ordner card
.
Diese Datei ist die Definition des Komponentendialogfelds für die Card
-Komponente. Bei Verwendung der Sling-Vererbung ist es möglich, Funktionen des Sling Resource Merger zu verwenden, um Teile des Dialogfelds zu überschreiben oder zu erweitern. In diesem Beispiel wurde dem Dialogfeld eine neue Registerkarte hinzugefügt, um zusätzliche Daten von einem Autor oder einer Autorin zu erfassen und die Kartenkomponente zu befüllen.
Mithilfe von Eigenschaften wie sling:orderBefore
kann ausgewählt werden, wo neue Registerkarten oder Formularfelder eingefügt werden sollen. In diesem Fall wird die Registerkarte Text
vor der Registerkarte asset
eingefügt. Um den Sling Resource Merger vollständig zu nutzen, ist es wichtig, die ursprüngliche Struktur der Dialogfeldknoten für das Dialogfeld „Bildkomponente“ zu kennen.
Öffnen Sie die Datei _cq_editConfig.xml
unter dem Ordner card
. Diese Datei bestimmt das Drag-and-Drop-Verhalten in der Authoring-Benutzeroberfläche von AEM. Bei der Erweiterung der Bildkomponente ist es wichtig, dass der Ressourcentyp der Komponente selbst entspricht. Überprüfen Sie den Knoten <parameters>
:
<parameters
jcr:primaryType="nt:unstructured"
sling:resourceType="wknd-spa-angular/components/card"
imageCrop=""
imageMap=""
imageRotate=""/>
Die meisten Komponenten erfordern keine cq:editConfig
, das Bild und untergeordnete Elemente der Bildkomponente sind Ausnahmen.
Wechseln Sie in der IDE zum Modul ui.frontend
und navigieren Sie zu ui.frontend/src/app/components/card
:
Überprüfen Sie die Datei card.component.ts
.
Die Komponente wurde bereits ausgelagert, um sie der AEM-Komponente Card
unter Verwendung der standardmäßigen MapTo
-Funktion zuzuordnen.
MapTo('wknd-spa-angular/components/card')(CardComponent, CardEditConfig);
Überprüfen Sie die drei @Input
-Parameter in der Klasse für src
, alt
und title
. Dies sind erwartete JSON-Werte aus der AEM Komponente, die der Angular-Komponente zugeordnet sind.
Öffnen Sie die Datei card.component.html
:
<div class="card" *ngIf="hasContent">
<app-image class="card__image" [src]="src" [alt]="alt" [title]="title"></app-image>
</div>
In diesem Beispiel haben wir die vorhandene Angular-Bildkomponente app-image
durch einfache Übergabe der @Input
-Parameter aus card.component.ts
wiederverwendet. Später im Tutorial werden zusätzliche Eigenschaften hinzugefügt und angezeigt.
Mit dieser ersten Implementierung von Card
wird die Funktionalität im AEM-SPA-Editor überprüft. Um die ursprüngliche Card
-Komponente zu sehen, ist eine Aktualisierung der Vorlagenrichtlinie erforderlich.
Stellen Sie den Starter-Code auf einer lokalen Instanz von AEM bereit, falls Sie dies noch nicht getan haben:
$ cd aem-guides-wknd-spa
$ mvn clean install -PautoInstallSinglePackage
Navigieren Sie zur SPA-Seitenvorlage unter http://localhost:4502/editor.html/conf/wknd-spa-angular/settings/wcm/templates/spa-page-template/structure.html.
Aktualisieren Sie die Richtlinie des Layout-Containers, um die neue Card
-Komponente als zulässige Komponente hinzuzufügen:
Speichern Sie die Änderungen an der Richtlinie und beobachten Sie die Card
-Komponente als zulässige Komponente:
Als Nächstes erstellen Sie die Card
-Komponente mit dem AEM-SPA-Editor.
Navigieren Sie zu http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html.
Im Modus Edit
fügen Sie die Card
-Komponente zum Layout Container
hinzu:
Ziehen Sie ein Bild aus dem Asset Finder und legen Sie es in der Card
-Komponente ab:
Öffnen Sie den Card
-Komponentendialog, wo Sie die neu hinzugefügte Registerkarte Text sehen.
Geben Sie die folgenden Werte in der Registerkarte Text ein:
Kartenpfad – Wählen Sie eine Seite unter der SPA Homepage aus.
CTA-Text – „Mehr erfahren“
Kartentitel – Leer lassen.
Titel von verknüpfter Seite abrufen – Aktivieren Sie das Kontrollkästchen, um dies auf „true“ zu setzen.
Aktualisieren Sie die Registerkarte Asset-Metadaten, um Werte für Alternativer Text und Beschriftung hinzuzufügen.
Derzeit werden nach der Aktualisierung des Dialogfelds keine weiteren Änderungen angezeigt. Um die neuen Felder für die Angular-Komponente verfügbar zu machen, müssen wir das Sling-Modell für die Card
-Komponente aktualisieren.
Öffnen Sie eine neue Registerkarte und navigieren Sie zu CRXDE-Lite. Suchen Sie in den Inhaltsknoten unterhalb von /content/wknd-spa-angular/us/en/home/jcr:content/root/responsivegrid
nach dem Inhalt der Komponente Card
.
Beachten Sie, dass die Eigenschaften cardPath
, ctaText
, titleFromPage
vom Dialogfeld beibehalten werden.
Um die Werte aus dem Komponentendialogfeld letztendlich für die Angular-Komponente verfügbar zu machen, müssen wir das Sling-Modell aktualisieren, das die JSON für die Card
-Komponente befüllt. Wir haben auch die Möglichkeit, zwei Elemente einer Business-Logik zu implementieren:
titleFromPage
auf wahr gesetzt ist, gib den Titel der durch cardPath
spezifizierten Seite zurück, andernfalls gib den Wert des Textfeldes cardTitle
zurück.cardPath
spezifizierten Seite zurück.Kehren Sie zur IDE Ihrer Wahl zurück und öffnen Sie das Modul core
.
Öffnen Sie die Datei Card.java
unter core/src/main/java/com/adobe/aem/guides/wknd/spa/angular/core/models/Card.java
.
Beachten Sie, dass die Schnittstelle Card
derzeit com.adobe.cq.wcm.core.components.models.Image
erweitert und daher die Methoden der Schnittstelle Image
erbt. Die Schnittstelle Image
erweitert bereits die Schnittstelle ComponentExporter
, über die das Sling-Modell als JSON exportiert und vom SPA-Editor zugeordnet werden kann. Daher müssen wir die Schnittstelle ComponentExporter
nicht explizit erweitern, wie wir es im Kapitel „Benutzerdefinierte Komponente“ getan haben.
Fügen Sie der Schnittstelle die folgenden Methoden hinzu:
@ProviderType
public interface Card extends Image {
/***
* The URL to populate the CTA button as part of the card.
* The link should be based on the cardPath property that points to a page.
* @return String URL
*/
public String getCtaLinkURL();
/***
* The text to display on the CTA button of the card.
* @return String CTA text
*/
public String getCtaText();
/***
* The date to be displayed as part of the card.
* This is based on the last modified date of the page specified by the cardPath
* @return
*/
public Calendar getCardLastModified();
/**
* Return the title of the page specified by cardPath if `titleFromPage` is set to true.
* Otherwise return the value of `cardTitle`
* @return
*/
public String getCardTitle();
}
Diese Methoden werden über die JSON-Modell-API bereitgestellt und an die Angular-Komponente übergeben.
Öffnen Sie CardImpl.java
. Dies ist die Implementierung der Schnittstelle Card.java
. Diese Implementierung wurde teilweise gekürzt, um das Tutorial zu beschleunigen. Beachten Sie die Verwendung der Anmerkungen @Model
und @Exporter
, um sicherzustellen, dass das Sling-Modell über den Sling Model Exporter als JSON serialisiert werden kann.
CardImpl.java
verwendet auch das Delegationsmuster für Sling-Modelle, um zu vermeiden, dass die Logik aus der Bild-Kernkomponente umgeschrieben wird.
Sehen Sie sich die folgenden Zeilen an:
@Self
@Via(type = ResourceSuperType.class)
private Image image;
Die obige Annotation instanziiert ein Bildobjekt mit dem Namen image
, basierend auf der Vererbung von sling:resourceSuperType
der Card
-Komponente.
@Override
public String getSrc() {
return null != image ? image.getSrc() : null;
}
Dann ist es möglich, einfach das Objekt image
für die Implementierung von Methoden zu verwenden, die von der Schnittstelle Image
definiert werden, ohne die Logik selbst schreiben zu müssen. Diese Technik wird für getSrc()
, getAlt()
und getTitle()
verwendet.
Implementieren Sie anschließend basierend auf dem Wert von cardPath
die Methode initModel()
zum Initiieren der privaten Variablen cardPage
.
@PostConstruct
public void initModel() {
if(StringUtils.isNotBlank(cardPath) && pageManager != null) {
cardPage = pageManager.getPage(this.cardPath);
}
}
@PostConstruct initModel()
wird aufgerufen, wenn das Sling-Modell initialisiert wird. Daher ist es eine gute Gelegenheit, Objekte zu initialisieren, die von anderen Methoden im Modell verwendet werden können. Der pageManager
ist eines von mehreren Java™-unterstützten globalen Objekten, die für Sling-Modelle über die Annotation @ScriptVariable
bereitgestellt werden. Die Methode getPage akzeptiert einen Pfad und gibt ein AEM-Seiten-Objekt zurück – oder null, wenn der Pfad nicht auf eine gültige Seite verweist.
Dadurch wird die Variable cardPage
initialisiert, die von den anderen neuen Methoden verwendet wird, um Daten zur zugrunde liegenden verknüpften Seite zurückzugeben.
Überprüfen Sie die globalen Variablen, die den JCR-Eigenschaften bereits zugeordnet und im Autorendialogfeld gespeichert sind. Die Annotation @ValueMapValue
wird verwendet, um die Zuordnung automatisch durchzuführen.
@ValueMapValue
private String cardPath;
@ValueMapValue
private String ctaText;
@ValueMapValue
private boolean titleFromPage;
@ValueMapValue
private String cardTitle;
Diese Variablen werden verwendet, um die zusätzlichen Methoden für die Schnittstelle Card.java
zu implementieren.
Implementieren Sie die zusätzlichen Methoden, die in der Schnittstelle Card.java
definiert sind:
@Override
public String getCtaLinkURL() {
if(cardPage != null) {
return cardPage.getPath() + ".html";
}
return null;
}
@Override
public String getCtaText() {
return ctaText;
}
@Override
public Calendar getCardLastModified() {
if(cardPage != null) {
return cardPage.getLastModified();
}
return null;
}
@Override
public String getCardTitle() {
if(titleFromPage) {
return cardPage != null ? cardPage.getTitle() : null;
}
return cardTitle;
}
Sie können die fertiggestellte CardImpl.java hier ansehen.
Öffnen Sie ein Terminal-Fenster und stellen Sie nur die Aktualisierungen des Moduls core
unter Verwendung des Maven-Profils autoInstallBundle
aus dem Verzeichnis core
bereit.
$ cd core/
$ mvn clean install -PautoInstallBundle
Wenn Sie AEM 6.x verwenden, fügen Sie das Profil classic
hinzu.
Öffnen Sie die JSON-Modellantwort unter http://localhost:4502/content/wknd-spa-angular/us/en.model.json und suchen Sie nach wknd-spa-angular/components/card
:
"card": {
"ctaText": "Read More",
"cardTitle": "Page 1",
"title": "Woman chillaxing with river views in Australian bushland",
"src": "/content/wknd-spa-angular/us/en/home/_jcr_content/root/responsivegrid/card.coreimg.jpeg/1595190732886/adobestock-216674449.jpeg",
"alt": "Female sitting on a large rock relaxing in afternoon dappled light the Australian bushland with views over the river",
"cardLastModified": 1591360492414,
"ctaLinkURL": "/content/wknd-spa-angular/us/en/home/page-1.html",
":type": "wknd-spa-angular/components/card"
}
Beachten Sie, dass das JSON-Modell zusätzliche Schlüssel/Wert-Paare erhält, nachdem die Methoden im Sling-Modell CardImpl
aktualisiert wurden.
Jetzt, da das JSON-Modell mit neuen Eigenschaften für ctaLinkURL
, ctaText
, cardTitle
und cardLastModified
befüllt ist, können wir die Angular-Komponente aktualisieren, um diese neuen Eigenschaften anzuzeigen.
Kehren Sie zur IDE zurück und öffnen Sie das Modul ui.frontend
. Optional können Sie den webpack-Development-Server über ein neues Terminal-Fenster starten, um die Änderungen in Echtzeit anzuzeigen:
$ cd ui.frontend
$ npm install
$ npm start
Öffnen Sie card.component.ts
unter ui.frontend/src/app/components/card/card.component.ts
. Fügen Sie die zusätzlichen @Input
-Anmerkungen hinzu, um das neue Modell zu erfassen:
export class CardComponent implements OnInit {
@Input() src: string;
@Input() alt: string;
@Input() title: string;
+ @Input() cardTitle: string;
+ @Input() cardLastModified: number;
+ @Input() ctaLinkURL: string;
+ @Input() ctaText: string;
Fügen Sie Methoden hinzu, um zu überprüfen, ob der Aktionsaufruf bereit ist, und um eine Datums-/Uhrzeitzeichenfolge basierend auf der Eingabe für cardLastModified
zurückzugeben:
export class CardComponent implements OnInit {
...
get hasCTA(): boolean {
return this.ctaLinkURL && this.ctaLinkURL.trim().length > 0 && this.ctaText && this.ctaText.trim().length > 0;
}
get lastModifiedDate(): string {
const lastModifiedDate = this.cardLastModified ? new Date(this.cardLastModified) : null;
if (lastModifiedDate) {
return lastModifiedDate.toLocaleDateString();
}
return null;
}
...
}
Öffnen Sie card.component.html
und fügen Sie das folgende Markup hinzu, um den Titel, den Aktionsaufruf und das Datum der letzten Änderung anzuzeigen:
<div class="card" *ngIf="hasContent">
<app-image class="card__image" [src]="src" [alt]="alt" [title]="title"></app-image>
<div class="card__content">
<h2 class="card__title">
{{cardTitle}}
<span class="card__lastmod" *ngIf="lastModifiedDate">{{lastModifiedDate}}</span>
</h2>
<div class="card__action-container" *ngIf="hasCTA">
<a [routerLink]="ctaLinkURL" class="card__action-link" [title]="ctaText">
{{ctaText}}
</a>
</div>
</div>
</div>
Sass-Regeln wurden bereits unter card.component.scss
hinzugefügt, um den Titel, den Aktionsaufruf und das Datum der letzten Änderung zu formatieren.
Sie können den fertigen Code der Angular-Kartenkomponente hier ansehen.
Stellen Sie die vollständigen Änderungen an AEM aus dem Stammverzeichnis des Projekts mithilfe von Maven bereit:
$ cd aem-guides-wknd-spa
$ mvn clean install -PautoInstallSinglePackage
Navigieren Sie zu http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html, um die aktualisierte Komponente anzuzeigen:
Sie sollten den vorhandenen Inhalt überarbeiten können, um eine Seite wie die folgende zu erstellen:
Herzlichen Glückwunsch! Sie haben gelernt, wie Sie eine AEM-Komponente erweitern und wie Sling-Modelle und -Dialogfelder mit dem JSON-Modell verwendet werden.
Sie können den fertigen Code jederzeit auf GitHub ansehen oder den Code lokal auschecken, indem Sie zur Verzweigung Angular/extend-component-solution
wechseln.