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, ist eine leistungsstarke Methode, um die Funktionen einer AEM SPA Editor-Implementierung anzupassen und zu erweitern.
sling:resourceSuperType
.Dieses Kapitel zeigt den zusätzlichen Code, der zum Hinzufügen einer zusätzlichen Eigenschaft zu einem Standard erforderlich ist Image
-Komponente, um die Anforderungen für eine neue Banner
-Komponente. Die Banner
-Komponente enthält alle gleichen Eigenschaften wie der Standard Image
-Komponente, enthält jedoch eine zusätzliche Eigenschaft, mit der Benutzer die Bannertext.
Überprüfen Sie die erforderlichen Tools und Anweisungen zum Einrichten eines lokale Entwicklungsumgebung. Es wird davon ausgegangen, dass die Benutzer des Tutorials zu diesem Zeitpunkt ein solides Verständnis der AEM SPA Editor-Funktion haben.
Um eine vorhandene Komponente zu erweitern, legen Sie eine Eigenschaft mit dem Namen fest sling:resourceSuperType
in der Definition Ihrer Komponente. sling:resourceSuperType
ist property , die für die Definition einer AEM Komponente festgelegt werden können, die auf eine andere Komponente verweist. Dadurch wird die Komponente explizit so eingestellt, dass sie alle Funktionen der Komponente übernimmt, die als sling:resourceSuperType
.
Wenn wir die Image
Komponente bei wknd-spa-react/components/image
Wir müssen den Code im ui.apps
-Modul.
Erstellen Sie einen neuen Ordner unter dem ui.apps
-Modul für banner
at ui.apps/src/main/content/jcr_root/apps/wknd-spa-react/components/banner
.
darunter banner
Erstellen einer Komponentendefinition (.content.xml
) wie folgt:
<?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="Banner"
sling:resourceSuperType="wknd-spa-react/components/image"
componentGroup="WKND SPA React - Content"/>
Diese Einstellung wknd-spa-react/components/banner
alle Funktionen von wknd-spa-react/components/image
.
Die _cq_editConfig.xml
-Datei bestimmt das Drag-and-Drop-Verhalten in der AEM Authoring-Benutzeroberfläche. Beim Erweitern der Bildkomponente ist es wichtig, dass der Ressourcentyp mit der Komponente selbst übereinstimmt.
Im ui.apps
-Modul erstellen Sie eine weitere Datei unter banner
benannt _cq_editConfig.xml
.
Auffüllen _cq_editConfig.xml
mit der folgenden XML-Datei:
<?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" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="cq:EditConfig">
<cq:dropTargets jcr:primaryType="nt:unstructured">
<image
jcr:primaryType="cq:DropTargetConfig"
accept="[image/gif,image/jpeg,image/png,image/webp,image/tiff,image/svg\\+xml]"
groups="[media]"
propertyName="./fileReference">
<parameters
jcr:primaryType="nt:unstructured"
sling:resourceType="wknd-spa-react/components/banner"
imageCrop=""
imageMap=""
imageRotate=""/>
</image>
</cq:dropTargets>
<cq:inplaceEditing
jcr:primaryType="cq:InplaceEditingConfig"
active="{Boolean}true"
editorType="image">
<inplaceEditingConfig jcr:primaryType="nt:unstructured">
<plugins jcr:primaryType="nt:unstructured">
<crop
jcr:primaryType="nt:unstructured"
supportedMimeTypes="[image/jpeg,image/png,image/webp,image/tiff]"
features="*">
<aspectRatios jcr:primaryType="nt:unstructured">
<wideLandscape
jcr:primaryType="nt:unstructured"
name="Wide Landscape"
ratio="0.6180"/>
<landscape
jcr:primaryType="nt:unstructured"
name="Landscape"
ratio="0.8284"/>
<square
jcr:primaryType="nt:unstructured"
name="Square"
ratio="1"/>
<portrait
jcr:primaryType="nt:unstructured"
name="Portrait"
ratio="1.6180"/>
</aspectRatios>
</crop>
<flip
jcr:primaryType="nt:unstructured"
supportedMimeTypes="[image/jpeg,image/png,image/webp,image/tiff]"
features="-"/>
<map
jcr:primaryType="nt:unstructured"
supportedMimeTypes="[image/jpeg,image/png,image/webp,image/tiff,image/svg+xml]"
features="*"/>
<rotate
jcr:primaryType="nt:unstructured"
supportedMimeTypes="[image/jpeg,image/png,image/webp,image/tiff]"
features="*"/>
<zoom
jcr:primaryType="nt:unstructured"
supportedMimeTypes="[image/jpeg,image/png,image/webp,image/tiff]"
features="*"/>
</plugins>
<ui jcr:primaryType="nt:unstructured">
<inline
jcr:primaryType="nt:unstructured"
toolbar="[crop#launch,rotate#right,history#undo,history#redo,fullscreen#fullscreen,control#close,control#finish]">
<replacementToolbars
jcr:primaryType="nt:unstructured"
crop="[crop#identifier,crop#unlaunch,crop#confirm]"/>
</inline>
<fullscreen jcr:primaryType="nt:unstructured">
<toolbar
jcr:primaryType="nt:unstructured"
left="[crop#launchwithratio,rotate#right,flip#horizontal,flip#vertical,zoom#reset100,zoom#popupslider]"
right="[history#undo,history#redo,fullscreen#fullscreenexit]"/>
<replacementToolbars jcr:primaryType="nt:unstructured">
<crop
jcr:primaryType="nt:unstructured"
left="[crop#identifier]"
right="[crop#unlaunch,crop#confirm]"/>
<map
jcr:primaryType="nt:unstructured"
left="[map#rectangle,map#circle,map#polygon]"
right="[map#unlaunch,map#confirm]"/>
</replacementToolbars>
</fullscreen>
</ui>
</inplaceEditingConfig>
</cq:inplaceEditing>
</jcr:root>
Der eindeutige Aspekt der Datei ist die <parameters>
-Knoten, der den resourceType auf wknd-spa-react/components/banner
.
<parameters
jcr:primaryType="nt:unstructured"
sling:resourceType="wknd-spa-react/components/banner"
imageCrop=""
imageMap=""
imageRotate=""/>
Die meisten Komponenten erfordern keine _cq_editConfig
. Bildkomponenten und untergeordnete Elemente bilden die Ausnahme.
Unsere Banner
-Komponente erfordert ein zusätzliches Textfeld im Dialogfeld, um die bannerText
. Da wir die Sling-Vererbung verwenden, können wir Funktionen der Sling Resource Merger , 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 zu erfassen und die Kartenkomponente zu füllen.
Im ui.apps
-Modul unter dem banner
Ordner erstellen, Ordner mit dem Namen _cq_dialog
.
darunter _cq_dialog
Dialogfelddefinitionsdatei erstellen .content.xml
. Füllen Sie es mit folgendem Inhalt:
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="nt:unstructured"
jcr:title="Banner"
sling:resourceType="cq/gui/components/authoring/dialog">
<content jcr:primaryType="nt:unstructured">
<items jcr:primaryType="nt:unstructured">
<tabs jcr:primaryType="nt:unstructured">
<items jcr:primaryType="nt:unstructured">
<text
jcr:primaryType="nt:unstructured"
jcr:title="Text"
sling:orderBefore="asset"
sling:resourceType="granite/ui/components/coral/foundation/container"
margin="{Boolean}true">
<items jcr:primaryType="nt:unstructured">
<columns
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"
margin="{Boolean}true">
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<textGroup
granite:hide="${cqDesign.titleHidden}"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/well">
<items jcr:primaryType="nt:unstructured">
<bannerText
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldDescription="Text to display on top of the banner."
fieldLabel="Banner Text"
name="./bannerText"/>
</items>
</textGroup>
</items>
</column>
</items>
</columns>
</items>
</text>
</items>
</tabs>
</items>
</content>
</jcr:root>
Die obige XML-Definition erstellt eine neue Registerkarte mit dem Namen Text und bestellen Sie sie before vorhandene Asset Registerkarte. Sie enthält ein einzelnes Feld. Bannertext.
Das Dialogfeld sieht wie folgt aus:
Beachten Sie, dass wir die Registerkarten für Asset oder Metadaten. Diese werden über die sling:resourceSuperType
-Eigenschaft.
Bevor wir eine Vorschau des Dialogfelds anzeigen können, müssen wir die SPA Komponente und die MapTo
-Funktion.
Um die Bannerkomponente mit dem SPA Editor zu verwenden, muss eine neue SPA-Komponente erstellt werden, die wknd-spa-react/components/banner
. Dies geschieht im ui.frontend
-Modul.
Im ui.frontend
Modul erstellen Sie einen neuen Ordner für Banner
at ui.frontend/src/components/Banner
.
Erstellen Sie eine neue Datei mit dem Namen Banner.js
unterhalb der Banner
Ordner. Füllen Sie es mit folgendem Inhalt:
import React, {Component} from 'react';
import {MapTo} from '@adobe/aem-react-editable-components';
export const BannerEditConfig = {
emptyLabel: 'Banner',
isEmpty: function(props) {
return !props || !props.src || props.src.trim().length < 1;
}
};
export default class Banner extends Component {
get content() {
return <img
className="Image-src"
src={this.props.src}
alt={this.props.alt}
title={this.props.title ? this.props.title : this.props.alt} />;
}
// display our custom bannerText property!
get bannerText() {
if(this.props.bannerText) {
return <h4>{this.props.bannerText}</h4>;
}
return null;
}
render() {
if (BannerEditConfig.isEmpty(this.props)) {
return null;
}
return (
<div className="Banner">
{this.bannerText}
<div className="BannerImage">{this.content}</div>
</div>
);
}
}
MapTo('wknd-spa-react/components/banner')(Banner, BannerEditConfig);
Diese SPA Komponente wird der AEM Komponente zugeordnet. wknd-spa-react/components/banner
zuvor erstellt wurde.
Aktualisieren import-components.js
at ui.frontend/src/components/import-components.js
, um die neue Banner
SPA Komponente:
import './ExperienceFragment/ExperienceFragment';
import './OpenWeather/OpenWeather';
+ import './Banner/Banner';
An dieser Stelle kann das Projekt in AEM bereitgestellt und das Dialogfeld getestet werden. Stellen Sie das Projekt mithilfe Ihrer Maven-Kenntnisse bereit:
$ cd aem-guides-wknd-spa.react
$ mvn clean install -PautoInstallSinglePackage
Aktualisieren Sie die Richtlinie der SPA, um die Banner
Komponente als Zulassungskomponente.
Navigieren Sie zu einer SPA Seite und fügen Sie die Banner
auf eine der SPA Seiten:
Im Dialogfeld können Sie einen Wert für Bannertext Dieser Wert wird jedoch nicht in der SPA-Komponente angezeigt. Dazu müssen wir das Sling-Modell für die Komponente erweitern.
Um die Werte aus dem Komponentendialogfeld letztendlich der React-Komponente bereitzustellen, müssen wir das Sling-Modell aktualisieren, das die JSON für die Banner
-Komponente. Dies geschieht im core
-Modul, das den gesamten Java-Code für unser SPA-Projekt enthält.
Zunächst erstellen wir eine neue Java-Schnittstelle für Banner
, die Image
Java-Schnittstelle.
Im core
-Modul erstellen Sie eine neue Datei mit dem Namen BannerModel.java
at core/src/main/java/com/adobe/aem/guides/wkndspa/react/core/models
.
Füllen Sie BannerModel.java
wie folgt:
package com.adobe.aem.guides.wkndspa.react.core.models;
import com.adobe.cq.wcm.core.components.models.Image;
import org.osgi.annotation.versioning.ProviderType;
@ProviderType
public interface BannerModel extends Image {
public String getBannerText();
}
Dadurch werden alle Methoden von der Kernkomponente übernommen Image
-Schnittstelle und fügen Sie eine neue Methode hinzu getBannerText()
.
Implementieren Sie als Nächstes das Sling-Modell für BannerModel
-Schnittstelle.
Im core
-Modul erstellen Sie eine neue Datei mit dem Namen BannerModelImpl.java
at core/src/main/java/com/adobe/aem/guides/wkndspa/react/core/models/impl
.
Füllen Sie BannerModelImpl.java
wie folgt:
package com.adobe.aem.guides.wkndspa.react.core.models.impl;
import com.adobe.aem.guides.wkndspa.react.core.models.BannerModel;
import com.adobe.cq.export.json.ComponentExporter;
import com.adobe.cq.export.json.ExporterConstants;
import com.adobe.cq.wcm.core.components.models.Image;
import org.apache.sling.models.annotations.*;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.Self;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
import org.apache.sling.models.annotations.via.ResourceSuperType;
@Model(
adaptables = SlingHttpServletRequest.class,
adapters = { BannerModel.class,ComponentExporter.class},
resourceType = BannerModelImpl.RESOURCE_TYPE,
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)
@Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION)
public class BannerModelImpl implements BannerModel {
// points to the the component resource path in ui.apps
static final String RESOURCE_TYPE = "wknd-spa-react/components/banner";
@Self
private SlingHttpServletRequest request;
// With sling inheritance (sling:resourceSuperType) we can adapt the current resource to the Image class
// this allows us to re-use all of the functionality of the Image class, without having to implement it ourself
// see https://github.com/adobe/aem-core-wcm-components/wiki/Delegation-Pattern-for-Sling-Models
@Self
@Via(type = ResourceSuperType.class)
private Image image;
// map the property saved by the dialog to a variable named `bannerText`
@ValueMapValue
private String bannerText;
// public getter to expose the value of `bannerText` via the Sling Model and JSON output
@Override
public String getBannerText() {
return bannerText;
}
// Re-use the Image class for all other methods:
@Override
public String getSrc() {
return null != image ? image.getSrc() : null;
}
@Override
public String getAlt() {
return null != image ? image.getAlt() : null;
}
@Override
public String getTitle() {
return null != image ? image.getTitle() : null;
}
// method required by `ComponentExporter` interface
// exposes a JSON property named `:type` with a value of `wknd-spa-react/components/banner`
// required to map the JSON export to the SPA component props via the `MapTo`
@Override
public String getExportedType() {
return BannerModelImpl.RESOURCE_TYPE;
}
}
Beachten Sie die Verwendung der @Model
und @Exporter
Anmerkungen, um sicherzustellen, dass das Sling-Modell über den Sling Model Exporter als JSON serialisiert werden kann.
BannerModelImpl.java
verwendet die Delegationsmuster für Sling-Modelle um zu vermeiden, dass die gesamte Logik aus der Bild-Kernkomponente umgeschrieben wird.
Überprüfen Sie die folgenden Zeilen:
@Self
@Via(type = ResourceSuperType.class)
private Image image;
Die obige Anmerkung instanziiert ein Bildobjekt mit dem Namen image
basierend auf der sling:resourceSuperType
Vererbung der Banner
-Komponente.
@Override
public String getSrc() {
return null != image ? image.getSrc() : null;
}
Dann ist es möglich, einfach die image
-Objekt, um Methoden zu implementieren, die von der Image
-Schnittstelle, ohne die Logik selbst schreiben zu müssen. Diese Technik wird für getSrc()
, getAlt()
und getTitle()
.
Öffnen Sie ein Terminal-Fenster und stellen Sie nur die Updates für core
-Modul mithilfe des Maven-Moduls autoInstallBundle
Profil aus core
Verzeichnis.
$ cd core/
$ mvn clean install -PautoInstallBundle
Kehren Sie zu AEM zurück und öffnen Sie die SPA Seite mit der Banner
-Komponente.
Aktualisieren Sie die Banner
Komponente einschließen Bannertext:
Füllen Sie die Komponente mit einem Bild:
Speichern Sie die Aktualisierungen des Dialogfelds.
Sie sollten jetzt den gerenderten Wert von Bannertext:
Zeigen Sie die JSON-Modellantwort unter: http://localhost:4502/content/wknd-spa-react/us/en.model.json und suchen Sie nach wknd-spa-react/components/card
:
"banner": {
"bannerText": "My Banner Text",
"src": "/content/wknd-spa-react/us/en/home/_jcr_content/root/responsivegrid/banner.coreimg.jpeg/1622167884688/sport-climbing.jpeg",
"alt": "alt banner rock climber",
":type": "wknd-spa-react/components/banner"
},
Beachten Sie, dass das JSON-Modell nach der Implementierung des Sling-Modells in mit zusätzlichen Schlüssel/Wert-Paaren aktualisiert wird. BannerModelImpl.java
.
Herzlichen Glückwunsch! Sie haben gelernt, wie eine AEM-Komponente mithilfe der erweitert wird und wie Sling-Modelle und -Dialogfelder mit dem JSON-Modell funktionieren.