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ê vai criar
Neste capítulo, um novo componente Card é criado. O componente Card estende o Componente principal da imagem adicionando campos de conteúdo adicionais, como um Título e um botão do Call to action, para executar a função de um teaser para outro conteúdo no SPA.
Card, dependendo dos requisitos do projeto. É sempre recomendável usar Componentes principais diretamente quando possível.Pré-requisitos
Revise 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. As imagens fornecidas pelo site de referência WKND são reutilizadas no SPA do WKND. O pacote pode ser instalado usando o Gerenciador de Pacotes da AEM.
do Gerenciador de Pacotes
Você sempre pode exibir o código concluído em GitHub ou conferir o código localmente alternando para a ramificação Angular/extend-component-solution.
Inspecionar implementação inicial da placa
Um componente Cartão inicial foi fornecido pelo código inicial do capítulo. Inspecione o ponto de partida para a implementação da placa.
-
No IDE de sua escolha, abra o módulo
ui.apps. -
Navegue até
ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/carde exiba o arquivo.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"/>A propriedade
sling:resourceSuperTypeaponta parawknd-spa-angular/components/image, indicando que o componenteCardherda a funcionalidade do componente de Imagem SPA WKND. -
Inspecione o arquivo
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:resourceSuperTypeaponta paracore/wcm/components/image/v2/image. Isso indica que o componente de Imagem SPA do WKND herda a funcionalidade da Imagem do componente principal.Também conhecido como Padrão de proxy, a herança de recursos do Sling é um padrão de design avançado que permite que os componentes secundários herdem funcionalidade e estendam/substituam o comportamento quando desejado. A herança do Sling oferece suporte a vários níveis de herança, de modo que, por fim, o novo componente
Cardherda a funcionalidade da Imagem do componente principal.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 do 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.
-
Abrir
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.
Você sempre pode exibir o código concluído em GitHub ou conferir o código localmente alternando para a ramificação Angular/extend-component-solution.