Ampliación de un componente principal extend-component
- El Editor universal para editar contenido sin encabezado de forma visual.
- El Editor de fragmentos de contenido para la edición de contenido sin encabezado basada en formularios.
Obtenga información sobre cómo ampliar un componente principal existente para utilizarlo con AEM SPA Editor. Comprender cómo ampliar un componente existente es una técnica potente para personalizar y ampliar las capacidades de una implementación de AEM SPA Editor.
Objetivo
- Ampliar un componente principal existente con propiedades y contenido adicionales.
- Comprenda los conceptos básicos de la herencia de componentes con el uso de
sling:resourceSuperType. - Aprenda a utilizar el Patrón de delegación para modelos Sling a fin de reutilizar la lógica y la funcionalidad existentes.
Lo qué va a generar
En este capítulo, se crea un nuevo componente Card. El componente Card amplía el componente principal de imagen al agregar campos de contenido adicionales como un título y un botón de Call to action para desempeñar la función de teaser de otro contenido dentro de la SPA.
Card según los requisitos del proyecto. Siempre se recomienda usar Componentes principales directamente cuando sea posible.Requisitos previos
Revise las herramientas y las instrucciones necesarias para configurar un entorno de desarrollo local.
Obtener el código
-
Descargue el punto de partida para este tutorial mediante Git:
code language-shell $ git clone git@github.com:adobe/aem-guides-wknd-spa.git $ cd aem-guides-wknd-spa $ git checkout Angular/extend-component-start -
Implemente el código base en una instancia local de AEM mediante Maven:
code language-shell $ mvn clean install -PautoInstallSinglePackageSi usa AEM 6.x, agregue el perfil
classic:code language-shell $ mvn clean install -PautoInstallSinglePackage -Pclassic -
Instale el paquete terminado para el sitio de referencia WKND tradicional. Las imágenes proporcionadas por sitio de referencia WKND se vuelven a utilizar en el SPA de WKND. El paquete se puede instalar usando Administrador de paquetes de AEM.
Siempre puede ver el código terminado en GitHub o consultarlo localmente cambiando a la rama Angular/extend-component-solution.
Inspeccionar la implementación inicial de la tarjeta
El código de inicio del capítulo ha proporcionado un componente de tarjeta inicial. Inspeccione el punto de partida para la implementación de la tarjeta.
-
En el IDE de su elección, abra el módulo
ui.apps. -
Vaya a
ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/cardy vea el archivo.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="Card" sling:resourceSuperType="wknd-spa-angular/components/image" componentGroup="WKND SPA Angular - Content"/>La propiedad
sling:resourceSuperTypeseñala awknd-spa-angular/components/image, lo que indica que el componenteCardhereda la funcionalidad del componente de imagen de SPA de WKND. -
Inspeccione el archivo
ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/image/.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="Image" sling:resourceSuperType="core/wcm/components/image/v2/image" componentGroup="WKND SPA Angular - Content"/>Observe que
sling:resourceSuperTypeseñala acore/wcm/components/image/v2/image. Esto indica que el componente de imagen de SPA de WKND hereda la funcionalidad de la imagen del componente principal.La herencia de recursos de Sling también conocida como Patrón proxy es un patrón de diseño potente que permite que los componentes secundarios hereden la funcionalidad y amplíen/anulen el comportamiento cuando lo deseen. La herencia de Sling admite varios niveles de herencia, por lo que, en última instancia, el nuevo componente
Cardhereda la funcionalidad de la imagen del componente principal.Many development teams strive to be D.R.Y. (don't repeat yourself). Sling inheritance makes this possible with AEM.
-
Beneath the
cardfolder, open the file_cq_dialog/.content.xml.This file is the Component Dialog definition for the
Cardcomponent. If using Sling inheritance, it is possible to use features of the Sling Resource Merger to override or extend portions of the dialog. In this sample, a new tab has been added to the dialog to capture additional data from an author to populate the Card Component.Properties like
sling:orderBeforeallow a developer to choose where to insert new tabs or form fields. In this case, theTexttab is inserted before theassettab. To make full use of the Sling Resource Merger, it is important to know the original dialog node structure for the Image component dialog. -
Beneath the
cardfolder, open the file_cq_editConfig.xml. This file dictates the drag and drop behavior in the AEM authoring UI. When extending the Image component, it is important that the resource type matches the component itself. Review the<parameters>node:code language-xml <parameters jcr:primaryType="nt:unstructured" sling:resourceType="wknd-spa-angular/components/card" imageCrop="" imageMap="" imageRotate=""/>Most components do not require a
cq:editConfig, the Image, and child descendents of the Image component are exceptions. -
In the IDE switch to the
ui.frontendmodule, navigating toui.frontend/src/app/components/card:
-
Inspeccione el archivo
card.component.ts.The component has already been stubbed out to map to the AEM
CardComponent using the standardMapTofunction.code language-js MapTo('wknd-spa-angular/components/card')(CardComponent, CardEditConfig);Review the three
@Inputparameters in the class forsrc,alt, andtitle. These are expected JSON values from the AEM component that are mapped to the Angular component. -
Open the file
card.component.html:code language-html <div class="card" *ngIf="hasContent"> <app-image class="card__image" [src]="src" [alt]="alt" [title]="title"></app-image> </div>In this example we chose to reuse the existing Angular Image component
app-imageby simply passing the@Inputparameters fromcard.component.ts. Later in the tutorial, additional properties are added and displayed.
Update the Template Policy
With this initial Card implementation review the functionality in the AEM SPA Editor. To see the initial Card component an update to the Template policy is needed.
-
Deploy the starter code to a local instance of AEM, if you haven't already:
code language-shell $ cd aem-guides-wknd-spa $ mvn clean install -PautoInstallSinglePackage -
Navigate to the SPA Page Template at http://localhost:4502/editor.html/conf/wknd-spa-angular/settings/wcm/templates/spa-page-template/structure.html.
-
Update the Layout Container's policy to add the new
Cardcomponent as an allowed component:
Save the changes to the policy, and observe the
Cardcomponent as an allowed component:
Author initial Card component
Next, author the Card component using the AEM SPA Editor.
-
Navigate to http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html.
-
In
Editmode, add theCardcomponent to theLayout Container:
-
Drag and drop an image from the Asset finder onto the
Cardcomponent:
-
Open the
Cardcomponent dialog and notice the addition of a Text Tab. -
Enter the following values on the Text tab:
Card Path - choose a page beneath the SPA homepage.
CTA Text - "Read More"
Card Title - leave blank
Get title from linked page - check the checkbox to indicate true.
-
Update the Asset Metadata tab to add values for Alternative Text and Caption.
Currently no additional changes appear after updating the dialog. To expose the new fields to the Angular Component, we need to update the Sling Model for the
Cardcomponent. -
Open a new tab and navigate to CRXDE-Lite. Inspect the content nodes beneath
/content/wknd-spa-angular/us/en/home/jcr:content/root/responsivegridto find theCardcomponent content.
Observe que el cuadro de diálogo mantiene las propiedades
cardPath,ctaText,titleFromPage.
Actualizar modelo de Sling de tarjeta
Para exponer finalmente los valores del cuadro de diálogo del componente al componente de Angular, necesitamos actualizar el modelo Sling que rellena el JSON para el componente Card. También tenemos la oportunidad de implementar dos partes de lógica empresarial:
- Si
titleFromPagetiene el valor true, devuelve el título de la página especificada porcardPath; de lo contrario, devuelve el valor del campo de textocardTitle. - Devuelve la última fecha de modificación de la página especificada por
cardPath.
Vuelva al IDE de su elección y abra el módulo core.
-
Open the file
Card.javaatcore/src/main/java/com/adobe/aem/guides/wknd/spa/angular/core/models/Card.java.Observe que la interfaz
Cardamplía actualmentecom.adobe.cq.wcm.core.components.models.Imagey, por lo tanto, hereda los métodos de la interfazImage. La interfazImageya amplía la interfazComponentExporter, lo que permite exportar el modelo Sling como JSON y asignarlo el editor de SPA. Por lo tanto, no es necesario ampliar explícitamente la interfazComponentExporter, como se hizo en el capítulo de componente personalizado. -
Añada los siguientes métodos a la interfaz:
code language-java @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(); }Estos métodos se exponen a través de la API del modelo JSON y se pasan al componente Angular.
-
Abra
CardImpl.java. Esta es la implementación de la interfazCard.java. Esta implementación se ha rellenado parcialmente para acelerar el tutorial. Observe el uso de las anotaciones@Modely@Exporterpara asegurarse de que el modelo Sling se pueda serializar como JSON a través del exportador del modelo Sling.CardImpl.javatambién usa el patrón de delegación para modelos Sling a fin de evitar que se vuelva a escribir la lógica desde el componente principal de imagen. -
Observe las líneas siguientes:
code language-java @Self @Via(type = ResourceSuperType.class) private Image image;La anotación anterior crea una instancia de un objeto de imagen denominado
imagebasado en la herenciasling:resourceSuperTypedel componenteCard.code language-java @Override public String getSrc() { return null != image ? image.getSrc() : null; }Entonces, es posible usar simplemente el objeto
imagepara implementar métodos definidos por la interfazImage, sin tener que escribir la lógica nosotros mismos. Esta técnica se usa paragetSrc(),getAlt()ygetTitle(). -
A continuación, implemente el método
initModel()para iniciar una variable privadacardPagebasada en el valor decardPathcode language-java @PostConstruct public void initModel() { if(StringUtils.isNotBlank(cardPath) && pageManager != null) { cardPage = pageManager.getPage(this.cardPath); } }Se llama al
@PostConstruct initModel()cuando se inicializa el modelo Sling, por lo que es una buena oportunidad para inicializar objetos que otros métodos del modelo pueden utilizar.pageManageres uno de varios objetos globales respaldados por Java™ disponibles para los modelos Sling a través de la anotación@ScriptVariable. El método getPage toma una ruta y devuelve un objeto Page de AEM o un valor nulo si la ruta no apunta a una página válida.Esto inicializa la variable
cardPage, que utilizan los otros métodos nuevos para devolver datos sobre la página vinculada subyacente. -
Revise las variables globales ya asignadas a las propiedades JCR guardadas en el cuadro de diálogo de autor. La anotación
@ValueMapValuese usa para realizar automáticamente la asignación.code language-java @ValueMapValue private String cardPath; @ValueMapValue private String ctaText; @ValueMapValue private boolean titleFromPage; @ValueMapValue private String cardTitle;Estas variables se utilizan para implementar los métodos adicionales para la interfaz
Card.java. -
Implemente los métodos adicionales definidos en la interfaz
Card.java:code language-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; }note note NOTE Puede ver CardImpl.java finalizado aquí. -
Abra una ventana de terminal e implemente solo las actualizaciones del módulo
coremediante el perfil MavenautoInstallBundledesde el directoriocore.code language-shell $ cd core/ $ mvn clean install -PautoInstallBundleSi usa AEM 6.x, agregue el perfil
classic. -
Vea la respuesta del modelo JSON en: http://localhost:4502/content/wknd-spa-angular/us/en.model.json y busque
wknd-spa-angular/components/card:code language-json "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" }Observe que el modelo JSON se actualiza con pares clave/valor adicionales después de actualizar los métodos en el modelo Sling
CardImpl.
Actualizar componente de Angular
Ahora que el modelo JSON se rellena con nuevas propiedades para ctaLinkURL, ctaText, cardTitle y cardLastModified, podemos actualizar el componente Angular para mostrarlas.
-
Vuelva al IDE y abra el módulo
ui.frontend. De forma opcional, inicie el servidor de desarrollo de Webpack desde una nueva ventana de terminal para ver los cambios en tiempo real:code language-shell $ cd ui.frontend $ npm install $ npm start -
Abra
card.component.tsa lasui.frontend/src/app/components/card/card.component.ts. Agregue las anotaciones adicionales de@Inputpara capturar el nuevo modelo:code language-diff 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; -
Agregue métodos para comprobar si Call to action está listo y devolver una cadena de fecha y hora basada en la entrada
cardLastModified:code language-js 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; } ... } -
Abra
card.component.htmly agregue las siguientes marcas para mostrar el título, la call to action y la fecha de la última modificación:code language-html <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>Ya se agregaron reglas Sass en
card.component.scsspara aplicar estilo al título, call to action y la fecha de la última modificación.note note NOTE Puede ver el código de componente de tarjeta Angular finalizado. -
Implemente los cambios completos en AEM desde la raíz del proyecto mediante Maven:
code language-shell $ cd aem-guides-wknd-spa $ mvn clean install -PautoInstallSinglePackage -
Vaya a http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html para ver el componente actualizado:
-
Debe poder volver a crear el contenido existente para crear una página similar a la siguiente:
Enhorabuena. congratulations
¡Enhorabuena! Ha aprendido a ampliar un componente de AEM y cómo los modelos Sling y los cuadros de diálogo funcionan con el modelo JSON.
Siempre puede ver el código terminado en GitHub o consultarlo localmente cambiando a la rama Angular/extend-component-solution.