Desenvolvimento de um componente personalizado para o AEM Screens

O tutorial a seguir percorre as etapas para criar um componente personalizado para o AEM Screens. A AEM Screens reutiliza muitos padrões e tecnologias de design existentes de outros produtos AEM. O tutorial destaca as diferenças e considerações especiais ao desenvolver para o AEM Screens.

Visão geral

Este tutorial destina-se a desenvolvedores novos no AEM Screens. Neste tutorial, um componente simples "Olá, mundo" é criado para um canal de sequência no AEM Screens. Uma caixa de diálogo permite que os autores atualizem o texto exibido.

visão geral

Pré-requisitos

Para concluir este tutorial, é necessário o seguinte:

  1. AEM 6.5 ou AEM 6.3 + Pacote de recursos do Screens mais recente

  2. Player do AEM Screens

  3. Ambiente de desenvolvimento local

As etapas e capturas de tela do tutorial são executadas usando CRXDE-Lite. IDEs também podem ser usados para concluir o tutorial. Mais informações sobre o uso de um IDE para desenvolvimento com AEM podem ser encontrados aqui.

Configuração do projeto

O código-fonte de um projeto do Screens geralmente é gerenciado como um projeto Maven de vários módulos. Para acelerar o tutorial, um projeto foi pré-gerado usando o Arquétipo de projeto 13 do AEM. Mais detalhes sobre a criação de um projeto com o Arquétipo de projeto Maven AEM pode ser encontrada aqui.

  1. Baixe e instale os seguintes pacotes usando Gerenciador de pacote do CRX:

Obter arquivo

Obter arquivo
Opcionalmente se trabalhar com o Eclipse ou outro IDE, faça o download do pacote de código-fonte abaixo. Implante o projeto em uma instância AEM local usando o comando Maven:

mvn -PautoInstallPackage clean install

Inicie o projeto We.Retail de telas SRC do HelloWorld

Obter arquivo

  1. Entrada Gerenciador de pacotes CRX verifique se os dois pacotes a seguir estão instalados:

    1. screens-weretail-run.ui.content-0.0.1-SNAPSHOT.zip
    2. screens-weretail-run.ui.apps-0.0.1-SNAPSHOT.zip

    Screens We.Retail Executar pacotes Ui.Apps e Ui.Content instalados via Gerenciador de pacotes do CRX

    Screens We.Retail Executar pacotes Ui.Apps e Ui.Content instalados via Gerenciador de pacotes do CRX

  2. A variável screens-weretail-run.ui.apps o pacote instala o código abaixo de /apps/weretail-run.

    Este pacote contém o código responsável pela renderização dos componentes personalizados do projeto. Este pacote inclui o código do componente e qualquer JavaScript ou CSS necessário. Este pacote também incorpora screens-weretail-run.core-0.0.1-SNAPSHOT.jar que contém qualquer código Java necessário para o projeto.

    OBSERVAÇÃO

    Neste tutorial, nenhum código Java é escrito. Se uma lógica de negócios mais complexa for necessária, o Java de back-end pode ser criado e implantado usando o pacote Java principal.

    Representação do código ui.apps no CRXDE Lite

    Representação do código ui.apps no CRXDE Lite

    A variável helloworld no momento, o componente é apenas um espaço reservado. Ao longo do tutorial, uma funcionalidade será adicionada permitindo que um autor atualize a mensagem exibida pelo componente.

  3. A variável screens-weretail-run.ui.content o pacote instala o código abaixo de:

    • /conf/we-retail-run
    • /content/dam/we-retail-run
    • /content/screens/we-retail-run

    Este pacote contém o conteúdo inicial e a estrutura de configuração necessária para o projeto. /conf/we-retail-run contém todas as configurações do projeto de execução We.Retail. /content/dam/we-retail-run inclui a inicialização de ativos digitais para o projeto. /content/screens/we-retail-run contém a estrutura de conteúdo do Screens. O conteúdo sob todos esses caminhos é atualizado principalmente no AEM. Para promover a consistência entre ambientes (local, desenvolvimento, preparo, produção), geralmente uma estrutura de conteúdo básica é salva no controle de origem.

  4. Navegue até o projeto AEM Screens > We.Retail Executar:

    No menu Iniciar AEM > Clique no ícone Screens. Verifique se o projeto executado We.Retail pode ser visto.

    we-retail-run-starter

Criar o componente Hello World

O componente Olá, mundo é um componente simples que permite que um usuário insira uma mensagem para ser exibida na tela. O componente é baseado no Modelo do componente de AEM Screens: https://github.com/Adobe-Marketing-Cloud/aem-screens-component-template.

O AEM Screens tem algumas restrições interessantes que não são necessariamente verdadeiras para componentes WCM tradicionais do Sites.

  • A maioria dos componentes do Screens precisa ser executada em tela cheia nos dispositivos de sinalização digital de destino
  • A maioria dos componentes do Screens precisa ser incorporável nos canais de sequência para gerar apresentações de slides
  • A criação deve permitir a edição de componentes individuais em um canal de sequência, portanto, renderizá-los em tela cheia está fora de questão
  1. Entrada CRXDE-Lite http://localhost:4502/crx/de/index.jsp (ou IDE de escolha) navegue até /apps/weretail-run/components/content/helloworld.

    Adicione as seguintes propriedades à helloworld componente:

        jcr:title="Hello World"
        sling:resourceSuperType="foundation/components/parbase"
        componentGroup="We.Retail Run - Content"
    

    Propriedades de /apps/weretail-run/components/content/helloworld

    Propriedades de /apps/weretail-run/components/content/helloworld

    A variável helloworld O componente estende a foundation/components/parbase para que possa ser usado corretamente dentro de um canal de sequência.

  2. Criar um arquivo abaixo de /apps/weretail-run/components/content/helloworld nomeado helloworld.html.

    Preencha o arquivo com o seguinte:

    <!--/*
    
     /apps/weretail-run/components/content/helloworld/helloworld.html
    
    */-->
    
    <!--/* production: preview authoring mode + unspecified mode (i.e. on publish) */-->
    <sly data-sly-test.production="${wcmmode.preview || wcmmode.disabled}" data-sly-include="production.html" />
    
    <!--/* edit: any other authoring mode, i.e. edit, design, scaffolding, etc. */-->
    <sly data-sly-test="${!production}" data-sly-include="edit.html" />
    

    Os componentes do Screens exigem duas renderizações diferentes, dependendo de qual modo de criação está sendo usada:

    1. Produção: modo de Visualização ou Publicação (wcmmode=disabled)
    2. Editar: usado para todos os outros modos de criação, ou seja, edição, design, andaimes, desenvolvedor…

    helloworld.htmlO atua como um switch, verificando qual modo de criação está ativo no momento e redirecionando para outro script HTL. Uma convenção comum usada por componentes de telas é ter uma edit.html script para o modo de Edição e um production.html para o modo de Produção.

  3. Criar um arquivo abaixo de /apps/weretail-run/components/content/helloworld nomeado production.html.

    Preencha o arquivo com o seguinte:

    <!--/*
     /apps/weretail-run/components/content/helloworld/production.html
    
    */-->
    
    <div data-duration="${properties.duration}" class="cmp-hello-world">
     <h1 class="cmp-hello-world__message">${properties.message}</h1>
    </div>
    

    Acima está a marcação de produção para o componente Hello World. A data-duration O atributo é incluído porque o componente é usado em um canal de Sequência. A variável data-duration O atributo é usado pelo canal de sequência para saber por quanto tempo um item de sequência deve ser exibido.

    O componente renderiza um div e uma h1 com texto. ${properties.message} é uma parte do script HTL que resultará no conteúdo de uma propriedade JCR chamada message. Uma caixa de diálogo é criada posteriormente permitindo que um usuário insira um valor para a variável message texto da propriedade.

    Observe também que a notação BEM (Block Element Modifier) é usada com o componente. BEM é uma convenção de codificação CSS que facilita a criação de componentes reutilizáveis. BEM é a notação usada por Componentes principais do AEM.

  4. Criar um arquivo abaixo de /apps/weretail-run/components/content/helloworld nomeado edit.html.

    Preencha o arquivo com o seguinte:

    <!--/*
    
     /apps/weretail-run/components/content/helloworld/edit.html
    
    */-->
    
    <!--/* if message populated */-->
    <div
     data-sly-test.message="${properties.message}"
     class="aem-Screens-editWrapper cmp-hello-world">
     <p class="cmp-hello-world__message">${message}</p>
    </div>
    
    <!--/* empty place holder */-->
    <div data-sly-test="${!message}"
         class="aem-Screens-editWrapper cq-placeholder cmp-hello-world"
         data-emptytext="${'Hello World' @ i18n, locale=request.locale}">
    </div>
    

    Acima está a marcação de edição do componente Hello World. O primeiro bloco exibe uma versão de edição do componente se a mensagem de diálogo tiver sido preenchida.

    O segundo bloco é renderizado se nenhuma mensagem de diálogo for inserida. A variável cq-placeholder e data-emptytext renderizar o rótulo Olá, mundo nesse caso, como titular. A string do rótulo pode ser internacionalizada usando o i18n para oferecer suporte à criação em vários locais.

  5. A caixa de diálogo Copiar imagem do Screens a ser usada para o componente Olá, mundo.

    É mais fácil começar com uma caixa de diálogo existente e, em seguida, fazer modificações.

    1. Copiar a caixa de diálogo de: /libs/screens/core/components/content/image/cq:dialog
    2. Colar a caixa de diálogo abaixo /apps/weretail-run/components/content/helloworld

    copy-image-dialog

  6. Atualize a caixa de diálogo Olá, mundo para incluir uma guia para a mensagem.

    Atualize a caixa de diálogo para que corresponda ao seguinte. A estrutura do nó JCR da caixa de diálogo final é apresentada abaixo em XML:

    <?xml version="1.0" encoding="UTF-8"?>
    <jcr:root xmlns:sling="https://sling.apache.org/jcr/sling/1.0" xmlns:cq="https://www.day.com/jcr/cq/1.0" xmlns:jcr="https://www.jcp.org/jcr/1.0" xmlns:nt="https://www.jcp.org/jcr/nt/1.0"
        jcr:primaryType="nt:unstructured"
        jcr:title="Hello World"
        sling:resourceType="cq/gui/components/authoring/dialog">
        <content
            jcr:primaryType="nt:unstructured"
            sling:resourceType="granite/ui/components/coral/foundation/tabs"
            size="L">
            <items jcr:primaryType="nt:unstructured">
                <message
                    jcr:primaryType="nt:unstructured"
                    jcr:title="Message"
                    sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns">
                    <items jcr:primaryType="nt:unstructured">
                        <column
                            jcr:primaryType="nt:unstructured"
                            sling:resourceType="granite/ui/components/coral/foundation/container">
                            <items jcr:primaryType="nt:unstructured">
                                <message
                                    jcr:primaryType="nt:unstructured"
                                    sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                    fieldDescription="Message for component to display"
                                    fieldLabel="Message"
                                    name="./message"/>
                            </items>
                        </column>
                    </items>
                </message>
                <sequence
                    jcr:primaryType="nt:unstructured"
                    jcr:title="Sequence"
                    sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns">
                    <items jcr:primaryType="nt:unstructured">
                        <column
                            jcr:primaryType="nt:unstructured"
                            sling:resourceType="granite/ui/components/coral/foundation/container">
                            <items jcr:primaryType="nt:unstructured">
                                <duration
                                    jcr:primaryType="nt:unstructured"
                                    sling:resourceType="granite/ui/components/coral/foundation/form/numberfield"
                                    defaultValue=""
                                    fieldDescription="Amount of time the image will be shown in the sequence, in milliseconds"
                                    fieldLabel="Duration (ms)"
                                    min="0"
                                    name="./duration"/>
                            </items>
                        </column>
                    </items>
                </sequence>
            </items>
        </content>
    </jcr:root>
    

    O campo de texto da mensagem será salvo em uma propriedade chamada message e que o campo numérico da Duração será salvo em uma propriedade chamada duration. Essas duas propriedades são referenciadas na /apps/weretail-run/components/content/helloworld/production.html por HTL como ${properties.message} e ${properties.duration}.

    Olá, mundo - caixa de diálogo concluída

    Olá, mundo - caixa de diálogo concluída

Criar bibliotecas do lado do cliente

As bibliotecas do lado do cliente fornecem um mecanismo para organizar e gerenciar arquivos CSS e JavaScript necessários para uma implementação do AEM.

Os componentes do AEM Screens são renderizados de forma diferente no modo Editar versus no modo Pré-visualização/Produção. Duas bibliotecas de clientes serão criadas, uma para o modo Editar e outra para o modo Visualização/Produção.

  1. Crie uma pasta para bibliotecas do lado do cliente para o componente Hello World.

    Abaixo /apps/weretail-run/components/content/helloworldcrie uma nova pasta chamada clientlibs.

    04/2018/30_às_1046h

  2. Abaixo de clientlibs pasta criar um novo nó chamado shared do tipo cq:ClientLibraryFolder.

    2018-04-30_às_1115h

  3. Adicione as seguintes propriedades à biblioteca de cliente compartilhada:

    • allowProxy | Booleano | true

    • categories| String[] | cq.screens.components

    Propriedades de /apps/weretail-run/components/content/helloworld/clientlibs/shared

    Propriedades de /apps/weretail-run/components/content/helloworld/clientlibs/shared

    A propriedade categories é uma string que identifica a biblioteca do cliente. A categoria cq.screens.components é usada nos modos Editar e Visualizar/Produção. Portanto, qualquer CSS/JS definido no sharedclientlib é carregado em todos os modos.

    É uma prática recomendada nunca expor nenhum caminho diretamente para /apps em um ambiente de produção. A propriedade allowProxy garante que o CSS e o JS da biblioteca do cliente sejam referenciados por meio de um prefixo of/etc.clientlibs.

  4. Criar arquivo chamado css.txt abaixo da pasta compartilhada.

    Preencha o arquivo com o seguinte:

    #base=css
    
    styles.less
    
  5. Crie uma pasta chamada css abaixo de shared pasta. Adicionar um arquivo chamado style.less abaixo de css pasta. A estrutura das bibliotecas de clientes agora deve ficar assim:

    2018-04-30_às_3_11h

    Em vez de escrever CSS diretamente, este tutorial usa MENOS. MENOS O é um pré-compilador de CSS popular que oferece suporte a variáveis, mixins e funções de CSS. Bibliotecas de clientes AEM nativamente oferecem suporte à compilação LESS. Sass ou outros pré-compiladores podem ser usados, mas precisam ser compilados fora do AEM.

  6. Preencher /apps/weretail-run/components/content/helloworld/clientlibs/shared/css/styles.less com o seguinte:

    /**
        Shared Styles
       /apps/weretail-run/components/content/helloworld/clientlibs/shared/css/styles.less
    
    **/
    
    .cmp-hello-world {
        background-color: #fff;
    
     &__message {
      color: #000;
      font-family: Helvetica;
      text-align:center;
     }
    }
    
  7. Copie e cole o shared pasta da biblioteca do cliente para criar uma nova biblioteca do cliente chamada production.

    Copie a biblioteca de cliente compartilhada para criar uma nova biblioteca de cliente de produção

    Copie a biblioteca de cliente compartilhada para criar uma nova biblioteca de cliente de produção

  8. Atualize o categories propriedade da biblioteca de cliente de produção a ser cq.screens.components.production.

    Isso garante que os estilos sejam carregados somente no modo de Pré-visualização/Produção.

    Propriedades de /apps/weretail-run/components/content/helloworld/clientlibs/production

    Propriedades de /apps/weretail-run/components/content/helloworld/clientlibs/production

  9. Preencher /apps/weretail-run/components/content/helloworld/clientlibs/production/css/styles.less com o seguinte:

    /**
        Production Styles
       /apps/weretail-run/components/content/helloworld/clientlibs/production/css/styles.less
    
    **/
    .cmp-hello-world {
    
        height: 100%;
        width: 100%;
        position: fixed;
    
     &__message {
    
      position: relative;
      font-size: 5rem;
      top:25%;
     }
    }
    

    Os estilos acima exibirão a mensagem centralizada no meio da tela, mas somente no modo de produção.

Uma terceira categoria de clientlibrary: cq.screens.components.edit pode ser usado para adicionar estilos específicos somente edição ao componente.

Categoria do Clientlib Uso
cq.screens.components Estilos e scripts compartilhados entre os modos de edição e de produção
cq.screens.components.edit Estilos e scripts que são usados somente no modo de edição
cq.screens.components.production Estilos e scripts que são usados somente no modo de produção

Criar uma página de design

O AEM Screens usa Modelos de página estáticos e Configurações de design para alterações globais. As configurações de design são usadas com frequência para configurar componentes permitidos para o Parsys em um canal. Uma prática recomendada é armazenar essas configurações de uma maneira específica do aplicativo.

Abaixo, uma página de Design de execução do We.Retail é criada e armazenará todas as configurações específicas do projeto de execução do We.Retail.

  1. Entrada CRXDE-Lite http://localhost:4502/crx/de/index.jsp#/apps/settings/wcm/designs navegue até /apps/settings/wcm/designs

  2. Crie um novo nó abaixo da pasta de designs, chamado we-retail-run com um tipo de cq:Page.

  3. Abaixo de we-retail-run adicione outro nó chamado jcr:content do tipo nt:unstructured. Adicione as seguintes propriedades à jcr:content nó:

    Nome Tipo Valor
    jcr:title String Execução do We.Retail
    sling:resourceType String wcm/core/components/designer
    cq:doctype String html_5

    Página de design em /apps/settings/wcm/designs/we-retail-run

    Página de design em /apps/settings/wcm/designs/we-retail-run

Criar um canal de sequência

O componente Hello World deve ser usado em um canal de sequência. Para testar o componente, um novo Canal de sequência é criado.

  1. No menu inicial do AEM, navegue até Screens > Execução do We.Retail n > e selecione Canais.

  2. Clique em Criar botão

    1. Escolher Criar entidade

    2018-04-30_às_5_18h

  3. No assistente Criar:

  4. Etapa de modelo - Escolher Canal de sequência

    1. Etapa Propriedades
    • Guia Básica > Título = Canal ocioso
    • Guia Canal > verificar Tornar o canal online

    idle-channel

  5. Abra as propriedades de página do Canal ocioso. Atualize o campo Design para apontar para /apps/settings/wcm/designs/we-retail-run,a página de design criada na seção anterior.

    Configuração de design /apps/settings/wcm/designs/we-retail-run

    Configuração de design apontando para /apps/settings/wcm/designs/we-retail-run

  6. Edite o canal ocioso recém-criado para abri-lo.

  7. Alternar o modo de página para Design Modo

    1. Clique em chave inglesa Ícone no Parsys para configurar os componentes permitidos

    2. Selecione o Screens e o Execução do We.Retail - Conteúdo grupo.

    2018-04-30_às_5_43h

  8. Alternar o modo de página para Editar. O componente Hello World agora pode ser adicionado à página e combinado com outros componentes de canal de sequência.

    2018-04-30_às_5_53h

  9. Entrada CRXDE-Lite http://localhost:4502/crx/de/index.jsp#/apps/settings/wcm/designs/we-retail-run/jcr%3Acontent/sequencechannel/par navegue até /apps/settings/wcm/designs/we-retail-run/jcr:content/sequencechannel/par. Observe a components A propriedade agora inclui group:Screens, group:We.Retail Run - Content.

    Configuração de design em /apps/settings/wcm/designs/we-retail-run

    Configuração de design em /apps/settings/wcm/designs/we-retail-run

Modelo para manipuladores personalizados

Caso seu componente personalizado esteja usando recursos externos, como ativos (imagens, vídeos, fontes, ícones etc.), representações de ativos específicas ou bibliotecas do lado do cliente (css, js etc.), eles não são adicionados automaticamente à configuração offline, pois agrupamos apenas a marcação HTML por padrão.

Para permitir que você personalize e otimize os ativos exatos que são baixados no reprodutor, oferecemos um mecanismo de extensão para que os componentes personalizados exponham suas dependências à lógica de armazenamento em cache offline no Screens.

A seção abaixo mostra o modelo para manipuladores de recursos offline personalizados e os requisitos mínimos na pom.xml para esse projeto específico.

package …;

import javax.annotation.Nonnull;

import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.ValueMap;

import com.adobe.cq.screens.visitor.OfflineResourceHandler;

@Service(value = OfflineResourceHandler.class)
@Component(immediate = true)
public class MyCustomHandler extends AbstractResourceHandler {

 @Reference
 private …; // OSGi services injection

 /**
  * The resource types that are handled by the handler.
  * @return the handled resource types
  */
 @Nonnull
 @Override
 public String[] getSupportedResourceTypes() {
     return new String[] { … };
 }

 /**
  * Accept the provided resource, visit and traverse it as needed.
  * @param resource The resource to accept
  */
 @Override
 public void accept(@Nonnull Resource resource) {
     ValueMap properties = ResourceUtil.getValueMap(resource);

     /* You can directly add explicit paths for offline caching using the `visit`
        method of the visitor. */

     // retrieve a custom property from the component
     String myCustomRenditionUrl = properties.get("myCustomRenditionUrl", String.class);
     // adding that exact asset/rendition/path to the offline manifest
     this.visitor.visit(myCustomRenditionUrl);


     /* You can delegate handling for dependent resources so they are also added to
        the offline cache using the `accept` method of the visitor. */

     // retrieve a referenced dependent resource
     String referencedResourcePath = properties.get("myOtherResource", String.class);
     ResourceResolver resolver = resource.getResourceResolver();
     Resource referencedResource = resolver.getResource(referencedResourcePath);
     // let the handler for that resource handle it
     if (referencedResource != null) {
         this.visitor.accept(referencedResource);
     }
   }
}

O código a seguir fornece os requisitos mínimos nas pom.xml para esse projeto específico:

   <dependencies>
        …
        <!-- Felix annotations -->
        <dependency>
            <groupId>org.apache.felix</groupId>
            <artifactId>org.apache.felix.scr.annotations</artifactId>
            <version>1.9.0</version>
            <scope>provided</scope>
        </dependency>

        <!-- Screens core bundle with OfflineResourceHandler/AbstractResourceHandler -->
        <dependency>
            <groupId>com.adobe.cq.screens</groupId>
            <artifactId>com.adobe.cq.screens</artifactId>
            <version>1.5.90</version>
            <scope>provided</scope>
        </dependency>
        …
      </dependencies>

Tudo junto na prática

O vídeo abaixo mostra o componente concluído e como ele pode ser adicionado a um canal de sequência. O Canal é então adicionado a uma exibição de Localização e, por fim, atribuído a um reprodutor do Screens.

Considerações adicionais para componentes personalizados que incorporam outras páginas ou fragmentos

Se o componente personalizado que você está desenvolvendo tiver a intenção de incluir outras páginas ou fragmentos de experiência e se você quiser que as alterações no conteúdo incorporado sejam automaticamente recebidas pelo reprodutor sem precisar republicar o canal, é necessário considerar estas duas restrições:

  1. Em vez de estender diretamente foundation/components/parbase, você teria que estender screens/core/components/content/page ou screens/core/components/content/experiencefragment
  2. O nome da propriedade usada para referenciar o conteúdo incorporado precisa ser pagePath

Aproveitar esses 2 componentes principais do Screens também vem com o benefício adicional de que eles podem cuidar de empacotar algumas das dependências que você precisa (bibliotecas do lado do cliente, fontes, etc.) por meio das opções de configuração offline na caixa de diálogo componente, o que reduz a responsabilidade de qualquer manipulador offline personalizado que você teria que usar para isso, às vezes até mesmo removendo completamente a necessidade de usar um.

Código concluído

Abaixo está o código concluído do tutorial. A variável screens-weretail-run.ui.apps-0.0.1-SNAPSHOT.zip e screens-weretail-run.ui.content-0.0.1-SNAPSHOT.zip são os pacotes de AEM compilados. O SRC-screens-weretail-run-0.0.1.zip ​ é o código-fonte não compilado que pode ser implantado usando Maven.

Obter arquivo

Obter arquivo

Obter arquivo

Nesta página