Scopri come estendere un componente core esistente da utilizzare con l’editor di SPA AEM. Scopri come estendere un componente esistente è una tecnica potente per personalizzare ed espandere le funzionalità di un’implementazione di AEM Editor .
sling:resourceSuperType
.In questo capitolo verrà creato un nuovo componente Card
. Il componente Card
estenderà il componente di base immagine aggiungendo ulteriori campi di contenuto, come un titolo e un pulsante Invito all’azione, per eseguire il ruolo di un teaser per altri contenuti all’interno del SPA.
In un’implementazione reale potrebbe essere più appropriato utilizzare semplicemente il componente teaser e quindi estendere il componente core immagine per creare un componente Card
in base ai requisiti del progetto. Si consiglia sempre di utilizzare Componenti core direttamente quando possibile.
Rivedi gli strumenti e le istruzioni necessari per configurare un ambiente di sviluppo locale.
Scarica il punto di partenza per questa esercitazione tramite Git:
$ git clone git@github.com:adobe/aem-guides-wknd-spa.git
$ cd aem-guides-wknd-spa
$ git checkout Angular/extend-component-start
Distribuisci la base di codice in un'istanza AEM locale utilizzando Maven:
$ mvn clean install -PautoInstallSinglePackage
Se utilizzi AEM 6.x aggiungi il profilo classic
:
$ mvn clean install -PautoInstallSinglePackage -Pclassic
Installa il pacchetto finito per il tradizionale sito di riferimento WKND. Le immagini fornite dal sito di riferimento WKND verranno riutilizzate nel SPA WKND. Il pacchetto può essere installato utilizzando Gestione pacchetti AEM.
Puoi sempre visualizzare il codice finito su GitHub o estrarre il codice localmente passando al ramo Angular/extend-component-solution
.
Il codice iniziale del capitolo fornisce un componente scheda iniziale. Inspect è il punto di partenza per l’implementazione di Card.
Nell’IDE che preferisci, apri il modulo ui.apps
.
Passa a ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/card
e visualizza il file .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="Card"
sling:resourceSuperType="wknd-spa-angular/components/image"
componentGroup="WKND SPA Angular - Content"/>
La proprietà sling:resourceSuperType
punta a wknd-spa-angular/components/image
per indicare che il componente Card
erediterà tutte le funzionalità dal componente Immagine SPA WKND.
Inspect il file 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"/>
Tieni presente che il sling:resourceSuperType
punta a core/wcm/components/image/v2/image
. Questo indica che il componente Immagine SPA WKND eredita tutte le funzionalità dall’immagine del componente core.
Anche noto come Pattern proxy ereditarietà di risorse Sling è un potente pattern di progettazione per consentire ai componenti secondari di ereditare le funzionalità ed estendere/sovrascrivere il comportamento quando desiderato. L’ereditarietà Sling supporta più livelli di ereditarietà, pertanto in ultima analisi il nuovo componente Card
eredita la funzionalità dell’immagine del componente core.
Molti team di sviluppo si sforzano di essere D.R.Y. (non ripetersi). L’ereditarietà Sling lo rende possibile con AEM.
Sotto la cartella card
, apri il file _cq_dialog/.content.xml
.
Questo file è la definizione della finestra di dialogo del componente Card
. Se si utilizza l'ereditarietà Sling, è possibile utilizzare le funzioni di Sling Resource Merger per sovrascrivere o estendere parti della finestra di dialogo. In questo esempio è stata aggiunta una nuova scheda alla finestra di dialogo per acquisire dati aggiuntivi da un autore per compilare il componente scheda.
Proprietà come sling:orderBefore
consentono agli sviluppatori di scegliere dove inserire nuove schede o campi modulo. In questo caso, la scheda Text
verrà inserita prima della scheda asset
. Per sfruttare appieno lo Sling Resource Merger è importante conoscere la struttura del nodo di dialogo originale per la finestra di dialogo Componente immagine.
Sotto la cartella card
, apri il file _cq_editConfig.xml
. Questo file determina il comportamento di trascinamento nell’interfaccia utente di AEM authoring. Quando estendi il componente Immagine, è importante che il tipo di risorsa corrisponda al componente stesso. Rivedi il nodo <parameters>
:
<parameters
jcr:primaryType="nt:unstructured"
sling:resourceType="wknd-spa-angular/components/card"
imageCrop=""
imageMap=""
imageRotate=""/>
La maggior parte dei componenti non richiede un cq:editConfig
, i discendenti immagine e figlio del componente Immagine sono eccezioni.
Nello switch IDE al modulo ui.frontend
, passa a ui.frontend/src/app/components/card
:
Inspect il file card.component.ts
.
Il componente è già stato arrestato per essere mappato sul componente AEM Card
utilizzando la funzione standard MapTo
.
MapTo('wknd-spa-angular/components/card')(CardComponent, CardEditConfig);
Esamina i tre parametri @Input
nella classe per src
, alt
e title
. Questi sono valori JSON attesi dal componente AEM che verrà mappato al componente Angular.
Aprire il file card.component.html
:
<div class="card" *ngIf="hasContent">
<app-image class="card__image" [src]="src" [alt]="alt" [title]="title"></app-image>
</div>
In questo esempio abbiamo scelto di riutilizzare il componente Immagine Angular esistente app-image
semplicemente passando i parametri @Input
da card.component.ts
. Successivamente nell’esercitazione verranno aggiunte e visualizzate altre proprietà.
Con questa implementazione iniziale Card
, controlla la funzionalità nell’editor di SPA AEM. Per visualizzare il componente iniziale Card
è necessario un aggiornamento al criterio del modello.
Distribuisci il codice iniziale in un'istanza locale di AEM, se non lo hai già fatto:
$ cd aem-guides-wknd-spa
$ mvn clean install -PautoInstallSinglePackage
Passa al SPA modello di pagina in http://localhost:4502/editor.html/conf/wknd-spa-angular/settings/wcm/templates/spa-page-template/structure.html.
Aggiorna i criteri del Contenitore di layout per aggiungere il nuovo componente Card
come componente consentito:
Salva le modifiche al criterio e osserva il componente Card
come componente consentito:
Quindi, crea il componente Card
utilizzando l’editor di SPA AEM.
Passa a http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html.
In modalità Edit
, aggiungi il componente Card
al Layout Container
:
Trascina un’immagine da Asset Finder al componente Card
:
Apri la finestra di dialogo del componente Card
e osserva l’aggiunta di una scheda Testo .
Immetti i seguenti valori nella scheda Testo :
Percorso scheda : scegli una pagina sotto la home page di SPA.
Testo CTA - "Ulteriori informazioni"
Titolo della scheda - Lascia vuoto
Ottieni titolo dalla pagina collegata: seleziona la casella di controllo per indicare true.
Aggiorna la scheda Metadati risorsa per aggiungere valori per Testo alternativo e Didascalia.
Al momento non vengono visualizzate ulteriori modifiche dopo l’aggiornamento della finestra di dialogo. Per esporre i nuovi campi al componente Angular, è necessario aggiornare il modello Sling per il componente Card
.
Apri una nuova scheda e passa a CRXDE-Lite. Inspect mostra i nodi di contenuto sotto /content/wknd-spa-angular/us/en/home/jcr:content/root/responsivegrid
per trovare il contenuto del componente Card
.
Osserva che le proprietà cardPath
, ctaText
, titleFromPage
vengono mantenute dalla finestra di dialogo.
Per esporre i valori dalla finestra di dialogo del componente al componente Angular, è necessario aggiornare il modello Sling che compila il JSON per il componente Card
. Abbiamo anche l'opportunità di implementare due elementi di logica di business:
titleFromPage
restituisce true, restituisce il titolo della pagina specificata da cardPath
altrimenti restituisce il valore di cardTitle
textfield.cardPath
.Torna all’IDE che preferisci e apri il modulo core
.
Apri il file Card.java
in core/src/main/java/com/adobe/aem/guides/wknd/spa/angular/core/models/Card.java
.
Osserva che l’interfaccia Card
al momento si estende com.adobe.cq.wcm.core.components.models.Image
e quindi eredita tutti i metodi dell’interfaccia Image
. L’interfaccia Image
estende già l’ interfaccia ComponentExporter
che consente di esportare il modello Sling come JSON e di mapparlo dall’editor SPA. Pertanto non è necessario estendere esplicitamente l'interfaccia ComponentExporter
come abbiamo fatto nel capitolo Componente personalizzato.
Aggiungi i seguenti metodi all’interfaccia:
@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();
}
Questi metodi verranno esposti tramite l’API del modello JSON e passati al componente Angular .
Apri CardImpl.java
. Questa è l’implementazione dell’interfaccia Card.java
. Questa implementazione è già stata parzialmente bloccata per accelerare l’esercitazione. Osserva l’uso delle annotazioni @Model
e @Exporter
per garantire che il modello Sling possa essere serializzato come JSON tramite l’esportatore di modelli Sling.
CardImpl.java
utilizza anche il pattern Delega per Sling Models per evitare di riscrivere tutta la logica dal componente di base Immagine .
Osserva le seguenti righe:
@Self
@Via(type = ResourceSuperType.class)
private Image image;
L’annotazione precedente crea un’istanza di un oggetto Immagine denominato image
in base all’ sling:resourceSuperType
ereditarietà del componente Card
.
@Override
public String getSrc() {
return null != image ? image.getSrc() : null;
}
È quindi possibile utilizzare semplicemente l'oggetto image
per implementare i metodi definiti dall'interfaccia Image
senza dover scrivere personalmente la logica. Questa tecnica viene utilizzata per getSrc()
, getAlt()
e getTitle()
.
Quindi, implementa il metodo initModel()
per avviare una variabile privata cardPage
in base al valore di cardPath
@PostConstruct
public void initModel() {
if(StringUtils.isNotBlank(cardPath) && pageManager != null) {
cardPage = pageManager.getPage(this.cardPath);
}
}
L’ @PostConstruct initModel()
viene sempre chiamato quando si inizializza il modello Sling, pertanto è una buona opportunità per inizializzare gli oggetti che possono essere utilizzati da altri metodi nel modello. Il pageManager
è uno dei numerosi oggetti globali Java supportati resi disponibili ai modelli Sling tramite l'annotazione @ScriptVariable
. Il metodo getPage accetta un percorso e restituisce un oggetto AEM Page o null se il percorso non punta a una pagina valida.
Viene inizializzata la variabile cardPage
, che verrà utilizzata dagli altri nuovi metodi per restituire i dati sulla pagina collegata sottostante.
Esamina le variabili globali già mappate alle proprietà JCR salvate nella finestra di dialogo dell’autore. L’annotazione @ValueMapValue
viene utilizzata per eseguire automaticamente la mappatura.
@ValueMapValue
private String cardPath;
@ValueMapValue
private String ctaText;
@ValueMapValue
private boolean titleFromPage;
@ValueMapValue
private String cardTitle;
Queste variabili verranno utilizzate per implementare i metodi aggiuntivi per l'interfaccia Card.java
.
Implementa i metodi aggiuntivi definiti nell'interfaccia Card.java
:
@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;
}
Puoi visualizzare il CardImpl.java finito qui.
Apri una finestra terminale e distribuisci solo gli aggiornamenti al modulo core
utilizzando il profilo Maven autoInstallBundle
dalla directory core
.
$ cd core/
$ mvn clean install -PautoInstallBundle
Se utilizzi AEM 6.x aggiungi il profilo classic
.
Visualizza la risposta del modello JSON in: http://localhost:4502/content/wknd-spa-angular/us/en.model.json e cerca il 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"
}
Nota che il modello JSON viene aggiornato con coppie chiave/valore aggiuntive dopo l’aggiornamento dei metodi nel modello CardImpl
Sling .
Ora che il modello JSON è popolato con nuove proprietà per ctaLinkURL
, ctaText
, cardTitle
e cardLastModified
, possiamo aggiornare il componente Angular per visualizzarli.
Torna all’IDE e apri il modulo ui.frontend
. Facoltativamente, avviare il server di sviluppo webpack da una nuova finestra terminale per visualizzare le modifiche in tempo reale:
$ cd ui.frontend
$ npm install
$ npm start
Apri card.component.ts
in ui.frontend/src/app/components/card/card.component.ts
. Aggiungi le annotazioni @Input
aggiuntive per acquisire il nuovo modello:
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;
Aggiungi i metodi per verificare se l’invito all’azione è pronto e per restituire una stringa di data/ora basata sull’input cardLastModified
:
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;
}
...
}
Apri card.component.html
e aggiungi il seguente markup per visualizzare il titolo, la chiamata all’azione e l’ultima data di modifica:
<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>
Le regole di base sono già state aggiunte in card.component.scss
per assegnare uno stile al titolo, alla chiamata all’azione e all’ultima data di modifica.
Puoi visualizzare il codice del componente della scheda di Angular completato qui.
Distribuisci le modifiche complete da AEM dalla radice del progetto utilizzando Maven:
$ cd aem-guides-wknd-spa
$ mvn clean install -PautoInstallSinglePackage
Passa a http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html per visualizzare il componente aggiornato:
È necessario poter creare nuovamente il contenuto esistente per creare una pagina simile alla seguente:
Congratulazioni, hai imparato a estendere un componente AEM utilizzando e come modelli e finestre di dialogo Sling funzionano con il modello JSON.
Puoi sempre visualizzare il codice finito su GitHub o estrarre il codice localmente passando al ramo Angular/extend-component-solution
.