Mapear componentes SPA para AEM componentes

Saiba como mapear componentes do Angular para componentes do Adobe Experience Manager (AEM) com o SDK JS do AEM SPA Editor. O mapeamento de componentes permite que os usuários façam atualizações dinâmicas em componentes SPA no Editor de SPA de AEM, de forma semelhante à criação tradicional de AEM.

Este capítulo aprofunda a API do modelo JSON do AEM e como o conteúdo JSON exposto por um componente AEM pode ser inserido automaticamente em um componente do Angular como props.

Objetivo

  1. Saiba como mapear componentes AEM para SPA componentes.
  2. Entenda a diferença entre os componentes Contêiner e Conteúdo.
  3. Crie um novo componente de Angular que mapeie para um componente de AEM existente.

O que você vai criar

Este capítulo verificará como o componente de SPA Text fornecido é mapeado para o componente de AEM Text. Um novo componente de SPA Image que pode ser usado no SPA e criado no AEM será criado. Os recursos prontos para uso das políticas Contêiner de layout e Editor de modelo também serão usados para criar uma exibição que é um pouco mais variada na aparência.

Criação final da amostra de capítulo

Pré-requisitos

Revise as ferramentas e instruções necessárias para configurar um ambiente de desenvolvimento local.

Obter o código

  1. Baixe o ponto de partida para este tutorial via Git:

    $ git clone git@github.com:adobe/aem-guides-wknd-spa.git
    $ cd aem-guides-wknd-spa
    $ git checkout Angular/map-components-start
    
  2. Implante a base de código em uma instância de AEM local usando o Maven:

    $ mvn clean install -PautoInstallSinglePackage
    

    Se estiver usando AEM 6.x adicione o perfil classic:

    $ mvn clean install -PautoInstallSinglePackage -Pclassic
    

Você sempre pode visualizar o código concluído em GitHub ou verificar o código localmente ao alternar para a ramificação Angular/map-components-solution.

Abordagem de mapeamento

O conceito básico é mapear um Componente de SPA para um Componente de AEM. AEM componentes, executar o lado do servidor e exportar conteúdo como parte da API do modelo JSON. O conteúdo JSON é consumido pelo SPA, executando no lado do cliente no navegador. Um mapeamento 1:1 entre SPA componentes e um componente AEM é criado.

Visão geral de alto nível do mapeamento de um componente de AEM para um componente de Angular

Visão geral de alto nível do mapeamento de um componente de AEM para um componente de Angular

Inspect o componente de texto

O AEM Arquétipo de Projeto fornece um componente Text que é mapeado para o AEM Componente de Texto. Este é um exemplo de um componente content, na medida em que renderiza content de AEM.

Vamos ver como o componente funciona.

Inspect o modelo JSON

  1. Antes de entrar no código SPA, é importante entender o modelo JSON que AEM fornece. Navegue até a Biblioteca de Componentes Principais e exiba a página do componente de Texto. A Biblioteca de componentes principais fornece exemplos de todos os componentes principais do AEM.

  2. Selecione a guia JSON para um dos exemplos:

    Modelo JSON de texto

    Você deve ver três propriedades: text, richText e :type.

    :type é uma propriedade reservada que lista o sling:resourceType (ou caminho) do Componente de AEM. O valor de :type é o que é usado para mapear o componente de AEM para o componente de SPA.

    text e richText são propriedades adicionais que serão expostas ao componente SPA.

Inspect o componente de texto

  1. Abra um novo terminal e navegue até a pasta ui.frontend dentro do projeto. Execute npm install e npm start para iniciar o servidor de desenvolvimento de webpack:

    $ cd ui.frontend
    $ npm run start:mock
    

    O módulo ui.frontend está configurado atualmente para usar o modelo JSON.

  2. Você deve ver uma nova janela do navegador aberta para http://localhost:4200/content/wknd-spa-angular/us/en/home.html

    Servidor de desenvolvimento do Webpack com conteúdo mock

  3. No IDE de sua escolha, abra o AEM Project para a SPA WKND. Expanda o módulo ui.frontend e abra o arquivo text.component.ts em ui.frontend/src/app/components/text/text.component.ts:

    Código-fonte do componente de Angular Text.js

  4. A primeira área a ser inspecionada é o class TextComponent em ~line 35:

    export class TextComponent {
        @Input() richText: boolean;
        @Input() text: string;
        @Input() itemName: string;
    
        @HostBinding('innerHtml') get content() {
            return this.richText
            ? this.sanitizer.bypassSecurityTrustHtml(this.text)
            : this.text;
        }
        @HostBinding('attr.data-rte-editelement') editAttribute = true;
    
        constructor(private sanitizer: DomSanitizer) {}
    }
    

    @Input() decorator é usado para declarar campos cujos valores estão definidos por meio do objeto JSON mapeado, revisado anteriormente.

    @HostBinding('innerHtml') get content() é um método que expõe o conteúdo do texto criado do valor de this.text. Caso o conteúdo seja rich text (determinado pelo sinalizador this.richText), a segurança interna do Angular é ignorada. O Angular DomSanitizer é usado para “depurar” o HTML bruto e evitar vulnerabilidades de script entre sites. O método é vinculado à propriedade innerHtml usando o decorador @HostBinding.

  5. Em seguida, inspecione o TextEditConfig em ~line 24:

    const TextEditConfig = {
        emptyLabel: 'Text',
        isEmpty: cqModel =>
            !cqModel || !cqModel.text || cqModel.text.trim().length < 1
    };
    

    O código acima é responsável por determinar quando renderizar o espaço reservado no ambiente de criação do AEM. Se o método isEmpty retornar true, o espaço reservado será renderizado.

  6. Por fim, dê uma olhada na chamada MapTo em ~line 53:

    MapTo('wknd-spa-angular/components/text')(TextComponent, TextEditConfig );
    

    ​MapTois fornecido pelo SDK JS do Editor de SPA AEM (@adobe/cq-angular-editable-components). O caminho wknd-spa-angular/components/text representa sling:resourceType do componente de AEM. Esse caminho é correspondido pelo :type exposto pelo modelo JSON observado anteriormente. ​MapToanalisa a resposta do modelo JSON e transmite os valores corretos para as @Input() variáveis do componente SPA.

    Você pode encontrar a definição AEM Text do componente em ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/text.

  7. Experimente modificar o arquivo en.model.json em ui.frontend/src/mocks/json/en.model.json.

    Em ~line 62, atualize o primeiro valor Text para usar as tags H1 e u:

        "text": {
            "text": "<h1><u>Hello World!</u></h1>",
            "richText": true,
            ":type": "wknd-spa-angular/components/text"
        }
    

    Retorne ao navegador para ver os efeitos oferecidos pelo servidor dev do webpack:

    Modelo de texto atualizado

    Tente alternar a propriedade richText entre true / false para ver a lógica de renderização em ação.

  8. Inspect text.component.html em ui.frontend/src/app/components/text/text.component.html.

    Este arquivo está vazio, pois todo o conteúdo do componente será definido pela propriedade innerHTML.

  9. Inspect o app.module.ts em ui.frontend/src/app/app.module.ts.

    @NgModule({
    imports: [
        BrowserModule,
        SpaAngularEditableComponentsModule,
        AppRoutingModule
    ],
    providers: [ModelManagerService, { provide: APP_BASE_HREF, useValue: '/' }],
    declarations: [AppComponent, TextComponent, PageComponent, HeaderComponent],
    entryComponents: [TextComponent, PageComponent],
    bootstrap: [AppComponent]
    })
    export class AppModule {}
    

    O TextComponent não é incluído explicitamente, mas sim dinamicamente por meio de AEMResponsiveGridComponent fornecido pelo SDK JS do Editor de SPA AEM. Portanto, deve ser listado na matriz app.module.ts' entryComponents.

Criar o componente de imagem

Em seguida, crie um componente de Angular Image que esteja mapeado para o componente de imagem AEM . O componente Image é outro exemplo de um componente content.

Inspect no JSON

Antes de saltar para o código SPA, inspecione o modelo JSON fornecido pelo AEM.

  1. Navegue até Exemplos de imagem na biblioteca do Componente principal.

    JSON do Componente principal de imagem

    As propriedades de src, alt e title serão usadas para preencher o componente de SPA Image.

    OBSERVAÇÃO

    Há outras propriedades de Imagem expostas (lazyEnabled, widths) que permitem que um desenvolvedor crie um componente adaptável e de carregamento lento. O componente criado neste tutorial será simples e not usará essas propriedades avançadas.

  2. Retorne ao IDE e abra en.model.json em ui.frontend/src/mocks/json/en.model.json. Como esse é um novo componente para nosso projeto, precisamos "zombar" o JSON da imagem.

    Em ~line 70, adicione uma entrada JSON para o modelo image (não se esqueça da vírgula à direita , depois do segundo text_386303036) e atualize a matriz :itemsOrder.

    ...
    ":items": {
                ...
                "text_386303036": {
                    "text": "<p>A new text component.</p>\r\n",
                    "richText": true,
                    ":type": "wknd-spa-angular/components/text"
                    },
                "image": {
                    "alt": "Rock Climber in New Zealand",
                    "title": "Rock Climber in New Zealand",
                    "src": "/mocks/images/adobestock-140634652.jpeg",
                    ":type": "wknd-spa-angular/components/image"
                }
            },
            ":itemsOrder": [
                "text",
                "text_386303036",
                "image"
            ],
    

    O projeto inclui uma imagem de amostra em /mock-content/adobestock-140634652.jpeg que será usada com o servidor dev do webpack.

    Você pode visualizar o en.model.json completo aqui.

  3. Adicione uma foto de estoque para ser exibida pelo componente.

    Crie uma nova pasta chamada images abaixo de ui.frontend/src/mocks. Baixe adobacrescentar-140634652.jpeg e coloque-o na pasta images recém-criada. Você pode usar sua própria imagem, se desejar.

Implementar o componente Imagem

  1. Pare o servidor de desenvolvimento do webpack, se iniciado.

  2. Crie um novo componente de Imagem executando o comando Angular CLI ng generate component da pasta ui.frontend:

    $ ng generate component components/image
    
  3. No IDE, abra image.component.ts em ui.frontend/src/app/components/image/image.component.ts e atualize da seguinte maneira:

    import {Component, Input, OnInit} from '@angular/core';
    import {MapTo} from '@adobe/cq-angular-editable-components';
    
    const ImageEditConfig = {
    emptyLabel: 'Image',
    isEmpty: cqModel =>
        !cqModel || !cqModel.src || cqModel.src.trim().length < 1
    };
    
    @Component({
    selector: 'app-image',
    templateUrl: './image.component.html',
    styleUrls: ['./image.component.scss']
    })
    export class ImageComponent implements OnInit {
    
    @Input() src: string;
    @Input() alt: string;
    @Input() title: string;
    
    constructor() { }
    
    get hasImage() {
        return this.src && this.src.trim().length > 0;
    }
    
    ngOnInit() { }
    }
    
    MapTo('wknd-spa-angular/components/image')(ImageComponent, ImageEditConfig);
    

    ImageEditConfig é a configuração para determinar se o espaço reservado do autor deve ser renderizado no AEM, com base em se a src propriedade foi preenchida.

    @Input() de src, alt e title são as propriedades mapeadas da API JSON.

    hasImage() é um método que determinará se a imagem deve ser renderizada.

    MapTo O mapeia o componente SPA para o componente AEM localizado em ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/image.

  4. Abra image.component.html e atualize-o da seguinte maneira:

    <ng-container *ngIf="hasImage">
        <img class="image" [src]="src" [alt]="alt" [title]="title"/>
    </ng-container>
    

    Isso renderizará o elemento <img> se hasImage retornar true.

  5. Abra image.component.scss e atualize-o da seguinte maneira:

    :host-context {
        display: block;
    }
    
    .image {
        margin: 1rem 0;
        width: 100%;
        border: 0;
    }
    
    OBSERVAÇÃO

    A regra :host-context é crítica para que o espaço reservado do editor de SPA AEM funcione corretamente. Todos os componentes de SPA que devem ser criados no editor de páginas de AEM precisarão dessa regra no mínimo.

  6. Abra app.module.ts e adicione ImageComponent à matriz entryComponents:

    entryComponents: [TextComponent, PageComponent, ImageComponent],
    

    Como TextComponent, ImageComponent é carregado dinamicamente e deve ser incluído na matriz entryComponents.

  7. Inicie o servidor dev do webpack para ver a renderização ImageComponent.

    $ npm run start:mock
    

    Imagem adicionada ao modelo

    Imagem adicionada ao SPA

    OBSERVAÇÃO

    Desafio extra: Implemente um novo método para exibir o valor de title como uma legenda abaixo da imagem.

Atualizar políticas no AEM

O componente ImageComponent é visível somente no servidor dev do webpack. Em seguida, implante o SPA atualizado para AEM e atualize as políticas do template.

  1. Pare o servidor de desenvolvimento de webpack e, a partir do root do projeto, implante as alterações para AEM usando suas habilidades Maven:

    $ cd aem-guides-wknd-spa
    $ mvn clean install -PautoInstallSinglePackage
    
  2. Na tela inicial AEM, navegue até Ferramentas > Modelos > Angular SPA WKND.

    Selecione e edite a Página SPA:

    Editar modelo de página SPA

  3. Selecione o Contêiner de layout e clique nele policy para editar a política:

    Política do contêiner de layout

  4. Em Componentes permitidos > Angular SPA WKND - Conteúdo > verifique o componente Imagem:

    Componente de imagem selecionado

    Em Componentes padrão > Adicionar mapeamento e escolha o componente Imagem - WKND SPA Angular - Conteúdo:

    Definir componentes padrão

    Insira um mime type de image/*.

    Clique em Concluído para salvar as atualizações de política.

  5. No Contêiner de layout clique no ícone política para o componente Texto:

    Ícone de política do componente de texto

    Crie uma nova política chamada Texto SPA WKND. Em Plugins > Formatação > marque todas as caixas para ativar opções adicionais de formatação:

    Ativar a formatação do RTE

    Em Plugins > Estilos de parágrafo > marque a caixa para Ativar estilos de parágrafo:

    Ativar estilos de parágrafo

    Clique em Concluído para salvar a atualização da política.

  6. Navegue até a Página inicial http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html.

    Você também deve poder editar o componente Text e adicionar estilos de parágrafo adicionais no modo tela cheia.

    Edição de rich text em tela cheia

  7. Você também deve ser capaz de arrastar e soltar uma imagem do Localizador de ativos:

    Arrastar e soltar imagem

  8. Adicione suas próprias imagens via AEM Assets ou instale a base de código finalizada para o site de referência WKND padrão. O site de referência WKND inclui muitas imagens que podem ser reutilizadas no SPA WKND. O pacote pode ser instalado usando AEM Gerenciador de Pacotes.

    O Gerenciador de Pacotes instala o wknd.all

Inspect no Contêiner de layout

O suporte para Contêiner de layout é fornecido automaticamente pelo SDK do Editor de SPA AEM. O Contêiner de layout, conforme indicado pelo nome, é um componente contêiner. Os componentes do contêiner são componentes que aceitam estruturas JSON que representam outros componentes e os instanciam dinamicamente.

Vamos inspecionar o Contêiner de layout ainda mais.

  1. No IDE, abra responsive-grid.component.ts em ui.frontend/src/app/components/responsive-grid:

    import { AEMResponsiveGridComponent,MapTo } from '@adobe/cq-angular-editable-components';
    
    MapTo('wcm/foundation/components/responsivegrid')(AEMResponsiveGridComponent);
    

    O AEMResponsiveGridComponent é implementado como parte do SDK do Editor de SPA AEM e é incluído no projeto por meio de import-components.

  2. Em um navegador, navegue até http://localhost:4502/content/wknd-spa-angular/us/en.model.json

    API do modelo JSON - Grade responsiva

    O componente Contêiner de layout tem um sling:resourceType de wcm/foundation/components/responsivegrid e é reconhecido pelo Editor de SPA usando a propriedade :type, exatamente como os componentes Text e Image.

    Os mesmos recursos de redimensionar um componente usando o Modo de layout estão disponíveis no Editor de SPA.

  3. Retorne para http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html. Adicione outros componentes Image e tente redimensioná-los usando a opção Layout:

    Redimensionar imagem usando o modo Layout

  4. Abra novamente o modelo JSON http://localhost:4502/content/wknd-spa-angular/us/en.model.json e observe o columnClassNames como parte do JSON:

    Nomes de classe da coluna

    O nome de classe aem-GridColumn--default--4 indica que o componente deve ter 4 colunas de largura com base em uma grade de 12 colunas. Mais detalhes sobre a grade responsiva podem ser encontrados aqui.

  5. Retorne ao IDE e no módulo ui.apps há uma biblioteca do lado do cliente definida em ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/clientlibs/clientlib-grid. Abra o arquivo less/grid.less.

    Esse arquivo determina os pontos de interrupção (default, tablet e phone) usados pelo Contêiner de layout. Este arquivo deve ser personalizado de acordo com as especificações do projeto. Atualmente, os pontos de interrupção estão definidos como 1200px e 650px.

  6. Você deve ser capaz de usar os recursos responsivos e as políticas de rich text atualizadas do componente Text para criar uma visualização como a seguinte:

    Criação final da amostra de capítulo

Parabéns!

Parabéns, você aprendeu a mapear componentes SPA para AEM Componentes e implementou um novo componente Image. Você também tem a chance de explorar os recursos responsivos do Contêiner de layout.

Você sempre pode visualizar o código concluído em GitHub ou verificar o código localmente ao alternar para a ramificação Angular/map-components-solution.

Próximas etapas

Navegação e roteamento - saiba como várias exibições no SPA podem ser compatíveis com o mapeamento para AEM páginas com o SDK do Editor SPA. A navegação dinâmica é implementada usando o Roteador de Angular e adicionada a um componente Cabeçalho existente.

Bônus - Persistir configurações no controle de origem

Em muitos casos, especialmente no início de um projeto AEM, é valioso manter configurações, como modelos e políticas de conteúdo relacionadas, para o controle de origem. Isso garante que todos os desenvolvedores estejam trabalhando com o mesmo conjunto de conteúdo e configurações e pode garantir uma consistência adicional entre os ambientes. Quando um projeto atinge um determinado nível de maturidade, a prática de gerenciar modelos pode ser transferida para um grupo especial de usuários avançados.

As próximas etapas serão executadas usando o Visual Studio Code IDE e VSCode AEM Sync, mas podem estar fazendo uso de qualquer ferramenta e de qualquer IDE que você tenha configurado para pull ou import conteúdo de uma instância local de AEM.

  1. No Visual Studio Code IDE, verifique se você tem VSCode AEM Sync instalado por meio da extensão Marketplace:

    Sincronização AEM VSCode

  2. Expanda o módulo ui.content no Gerenciador de projetos e navegue até /conf/wknd-spa-angular/settings/wcm/templates.

  3. Clique com o botão direito do mouse na templates pasta e selecione Importar de AEM Servidor:

    Modelo de importação do VSCode

  4. Repita as etapas para importar conteúdo, mas selecione a pasta policies localizada em /conf/wknd-spa-angular/settings/wcm/policies.

  5. Inspect o arquivo filter.xml localizado em ui.content/src/main/content/META-INF/vault/filter.xml.

    <!--ui.content filter.xml-->
    <?xml version="1.0" encoding="UTF-8"?>
     <workspaceFilter version="1.0">
         <filter root="/conf/wknd-spa-angular" mode="merge"/>
         <filter root="/content/wknd-spa-angular" mode="merge"/>
         <filter root="/content/dam/wknd-spa-angular" mode="merge"/>
         <filter root="/content/experience-fragments/wknd-spa-angular" mode="merge"/>
     </workspaceFilter>
    

    O arquivo filter.xml é responsável por identificar os caminhos dos nós que serão instalados com o pacote. Observe o mode="merge" em cada um dos filtros, que indica que o conteúdo existente não será modificado, somente o novo conteúdo será adicionado. Como os autores de conteúdo podem estar atualizando esses caminhos, é importante que uma implantação de código not substitua o conteúdo. Consulte a documentação do FileVault para obter mais detalhes sobre como trabalhar com elementos de filtro.

    Compare ui.content/src/main/content/META-INF/vault/filter.xml e ui.apps/src/main/content/META-INF/vault/filter.xml para entender os diferentes nós gerenciados por cada módulo.

Nesta página