Estender um Componente principal extend-component
- O editor universal para editar conteúdo headless visualmente.
- O editor de fragmentos de conteúdo para editar conteúdo headless com base em formulários.
Saiba como estender um Componente principal existente para ser usado com o Editor SPA do AEM. Entender como estender um componente existente é uma técnica poderosa para personalizar e expandir os recursos de uma implementação do Editor SPA do AEM.
Objetivo
- Estender um Componente principal existente com propriedades e conteúdo adicionais.
- Entenda o básico da Herança de componentes com o uso de
sling:resourceSuperType. - Saiba como usar o Padrão de delegação para Modelos do Sling para reutilizar a lógica e a funcionalidade existentes.
O que você criará
In this chapter, a new Card component is created. The Card component extends the Image Core Component adding additional content fields like a Title and a Call To Action button to perform the role of a teaser for other content within the SPA.
Card component depending on project requirements. It is always recommended to use Core Components directly when possible.Pré-requisitos
Consulte as ferramentas e instruções necessárias para configurar um ambiente de desenvolvimento local.
Obter o código
-
Baixe o ponto de partida para este tutorial pelo 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 -
Implante a base de código em uma instância do AEM local usando Maven:
code language-shell $ mvn clean install -PautoInstallSinglePackageSe estiver usando o AEM 6.x, adicione o perfil
classic:code language-shell $ mvn clean install -PautoInstallSinglePackage -Pclassic -
Instale o pacote concluído para o site de referência WKND tradicional. The images provided by WKND reference site is reused on the WKND SPA. O pacote pode ser instalado usando o Gerenciador de Pacotes da AEM.
do Gerenciador de Pacotes
É sempre possível exibir o código concluído no GitHub ou conferir o código localmente, alternando-se para a ramificação Angular/extend-component-solution.
Inspect initial Card implementation
An initial Card Component has been provided by the chapter starter code. Inspect the starting point for the Card implementation.
-
In the IDE of your choice open the
ui.appsmodule. -
Navigate to
ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/cardand view the.content.xmlfile.
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"/>The property
sling:resourceSuperTypepoints towknd-spa-angular/components/imageindicating that theCardcomponent inherits the functionality from the WKND SPA Image component. -
Inspect the file
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"/>Notice that the
sling:resourceSuperTypepoints tocore/wcm/components/image/v2/image. This indicates that the WKND SPA Image component inherits the functionality from the Core Component Image.Also known as the Proxy pattern Sling resource inheritance is a powerful design pattern for allowing child components to inherit functionality and extend/override behavior when desired. Sling inheritance supports multiple levels of inheritance, so ultimately the new
Cardcomponent inherits functionality of the Core Component Image.Muitas equipes de desenvolvimento se esforçam para ser D.R.Y. (não se repita). A herança do Sling torna isso possível com o AEM.
-
Abaixo da pasta
card, abra o arquivo_cq_dialog/.content.xml.Este arquivo é a definição de Caixa de Diálogo de Componente para o componente
Card. Se estiver usando a herança do Sling, é possível usar os recursos do Sling Resource Merger para substituir ou estender partes da caixa de diálogo. Neste exemplo, uma nova guia foi adicionada à caixa de diálogo para capturar dados adicionais de um autor para preencher o componente Cartão.Propriedades como
sling:orderBeforepermitem que um desenvolvedor escolha onde inserir novas guias ou campos de formulário. Nesse caso, a guiaTexté inserida antes da guiaasset. Para usar totalmente o Sling Resource Merger, é importante conhecer a estrutura original do nó de diálogo da caixa de diálogo do componente de Imagem. -
Abaixo da pasta
card, abra o arquivo_cq_editConfig.xml. Esse arquivo determina o comportamento de arrastar e soltar na interface de criação do AEM. Ao estender o componente de Imagem, é importante que o tipo de recurso corresponda ao próprio componente. Revise o nó<parameters>:code language-xml <parameters jcr:primaryType="nt:unstructured" sling:resourceType="wknd-spa-angular/components/card" imageCrop="" imageMap="" imageRotate=""/>A maioria dos componentes não requer um
cq:editConfig. A Imagem e os descendentes secundários do componente de Imagem são exceções. -
No IDE, alterne para o módulo
ui.frontend, navegando paraui.frontend/src/app/components/card:
-
Inspecione o arquivo
card.component.ts.O componente já foi esvaziado para mapear para o Componente
Carddo AEM usando a funçãoMapTopadrão.code language-js MapTo('wknd-spa-angular/components/card')(CardComponent, CardEditConfig);Revise os três parâmetros
@Inputna classe parasrc,altetitle. Esses são valores JSON esperados do componente AEM que são mapeados para o componente Angular. -
Abra o arquivo
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>Neste exemplo, optamos por reutilizar o componente de Imagem do Angular existente
app-imagesimplesmente passando os parâmetros@Inputdecard.component.ts. Posteriormente no tutorial, propriedades adicionais são adicionadas e exibidas.
Atualizar a política do modelo
Com esta implementação inicial Card, analise a funcionalidade no Editor SPA do AEM. Para ver o componente Card inicial, é necessário atualizar a diretiva Modelo.
-
Implante o código inicial em uma instância local do AEM, se você ainda não tiver:
code language-shell $ cd aem-guides-wknd-spa $ mvn clean install -PautoInstallSinglePackage -
Navegue até o Modelo de Página de SPA em http://localhost:4502/editor.html/conf/wknd-spa-angular/settings/wcm/templates/spa-page-template/structure.html.
-
Atualize a política do Contêiner de Layout para adicionar o novo componente
Cardcomo um componente permitido:
Salve as alterações na política e observe o componente
Cardcomo um componente permitido:
Componente Cartão inicial do autor
Em seguida, crie o componente Card usando o Editor SPA do AEM.
-
Navegue até http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html.
-
No modo
Edit, adicione o componenteCardaLayout Container:
-
Arraste e solte uma imagem do Localizador de ativos no componente
Card:
-
Abra a caixa de diálogo do componente
Carde observe a adição de uma guia Texto. -
Insira os seguintes valores na guia Texto:
Caminho do cartão - escolha uma página abaixo da página inicial do SPA.
Texto Do CTA - "Leia Mais"
Título do cartão - deixe em branco
Obter título da página vinculada - marque a caixa de seleção para indicar verdadeiro.
-
Atualize a guia Metadados do ativo para adicionar valores para Texto alternativo e Legenda.
No momento, nenhuma alteração adicional é exibida após a atualização da caixa de diálogo. Para expor os novos campos ao componente do Angular, precisamos atualizar o Modelo Sling do componente
Card. -
Abra uma nova guia e navegue até CRXDE-Lite. Inspecione os nós de conteúdo abaixo de
/content/wknd-spa-angular/us/en/home/jcr:content/root/responsivegridpara localizar o conteúdo do componenteCard.
Observe que as propriedades
cardPath,ctaText,titleFromPagesão mantidas pela caixa de diálogo.
Atualizar modelo Sling do cartão
Para expor os valores da caixa de diálogo do componente para o componente Angular, precisamos atualizar o Modelo do Sling que preenche o JSON para o componente Card. Também temos a oportunidade de implementar duas partes da lógica de negócios:
- Se
titleFromPagefor true, retorna o título da página especificada porcardPath; caso contrário, retorna o valor de textfieldcardTitle. - Retorna a data da última modificação da página especificada por
cardPath.
Retorne ao IDE de sua escolha e abra o módulo core.
-
Abra o arquivo
Card.javaemcore/src/main/java/com/adobe/aem/guides/wknd/spa/angular/core/models/Card.java.Observe que a interface
Cardestende atualmentecom.adobe.cq.wcm.core.components.models.Imagee, portanto, herda os métodos da interfaceImage. A interfaceImagejá estende a interfaceComponentExporter, o que permite que o Modelo Sling seja exportado como JSON e mapeado pelo editor de SPA. Portanto, não precisamos estender explicitamente a interfaceComponentExportercomo fizemos no capítulo Componente personalizado. -
Adicione os seguintes métodos à interface:
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(); }Esses métodos são expostos por meio da API do modelo JSON e passados para o componente Angular.
-
Abra
CardImpl.java. Esta é a implementação da interfaceCard.java. Esta implementação foi parcialmente removida para acelerar o tutorial. Observe o uso das anotações@Modele@Exporterpara garantir que o Modelo do Sling possa ser serializado como JSON por meio do Exportador de modelos do Sling.CardImpl.javatambém usa o padrão de Delegação para Modelos Sling para evitar a regravação da lógica do Componente principal de imagem. -
Observe as seguintes linhas:
code language-java @Self @Via(type = ResourceSuperType.class) private Image image;A anotação acima instancia um objeto de Imagem chamado
imagecom base na herançasling:resourceSuperTypedo componenteCard.code language-java @Override public String getSrc() { return null != image ? image.getSrc() : null; }Portanto, é possível simplesmente usar o objeto
imagepara implementar métodos definidos pela interfaceImage, sem precisar gravar a lógica. Esta técnica é usada paragetSrc(),getAlt()egetTitle(). -
Em seguida, implemente o método
initModel()para iniciar uma variável privadacardPagecom base no valor decardPathcode language-java @PostConstruct public void initModel() { if(StringUtils.isNotBlank(cardPath) && pageManager != null) { cardPage = pageManager.getPage(this.cardPath); } }O
@PostConstruct initModel()é chamado quando o Modelo Sling é inicializado, portanto, é uma boa oportunidade para inicializar objetos que podem ser usados por outros métodos no modelo.pageManageré um dos vários objetos globais com suporte de Java™ disponibilizados para Modelos Sling através da anotação@ScriptVariable. O método getPage pega um caminho e retorna um objeto AEM Page ou é nulo se o caminho não apontar para uma página válida.Isso inicializa a variável
cardPage, que é usada por outros novos métodos para retornar dados sobre a página vinculada subjacente. -
Revise as variáveis globais já mapeadas para as propriedades JCR salvas na caixa de diálogo do autor. A anotação
@ValueMapValueé usada para executar o mapeamento automaticamente.code language-java @ValueMapValue private String cardPath; @ValueMapValue private String ctaText; @ValueMapValue private boolean titleFromPage; @ValueMapValue private String cardTitle;Essas variáveis são usadas para implementar os métodos adicionais para a interface
Card.java. -
Implementar os métodos adicionais definidos na interface
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 Você pode exibir o CardImpl.java concluído aqui. -
Abra uma janela de terminal e implante apenas as atualizações para o módulo
coreusando o perfil MavenautoInstallBundledo diretóriocore.code language-shell $ cd core/ $ mvn clean install -PautoInstallBundleSe estiver usando o AEM 6.x, adicione o perfil
classic. -
Exiba a resposta do modelo JSON em: http://localhost:4502/content/wknd-spa-angular/us/en.model.json e pesquise por
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 o modelo JSON é atualizado com pares de chave/valor adicionais após a atualização dos métodos no Modelo Sling
CardImpl.
Atualizar componente do Angular
Agora que o modelo JSON foi preenchido com novas propriedades para ctaLinkURL, ctaText, cardTitle e cardLastModified, podemos atualizar o componente Angular para exibi-las.
-
Retorne ao IDE e abra o módulo
ui.frontend. Como opção, inicie o servidor de desenvolvimento do webpack a partir de uma nova janela do terminal para ver as alterações em tempo real:code language-shell $ cd ui.frontend $ npm install $ npm start -
Abrir
card.component.tsemui.frontend/src/app/components/card/card.component.ts. Adicionar as@Inputanotações adicionais para capturar o novo 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; -
Adicione métodos para verificar se o Call to action está pronto e para retornar uma cadeia de caracteres de data/hora com base na 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.htmle adicione a seguinte marcação para exibir o título, o call to action e a data da última modificação: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>As regras de acesso já foram adicionadas em
card.component.scsspara criar o estilo do título, call to action e data da última modificação.note note NOTE Você pode exibir o código do componente do cartão do Angular concluído aqui. -
Implante as alterações completas no AEM a partir da raiz do projeto usando o Maven:
code language-shell $ cd aem-guides-wknd-spa $ mvn clean install -PautoInstallSinglePackage -
Navegue até http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html para ver o componente atualizado:
-
Você deve ser capaz de recriar o conteúdo existente para criar uma página semelhante ao seguinte:
Parabéns! congratulations
Parabéns, você aprendeu a estender um componente do AEM e como os Modelos e caixas de diálogo do Sling funcionam com o modelo JSON.
É sempre possível exibir o código concluído no GitHub ou conferir o código localmente, alternando-se para a ramificação Angular/extend-component-solution.