O tutorial a seguir apresenta as etapas para criar um componente personalizado para AEM Screens. A AEM Screens reutiliza muitos padrões e tecnologias de design existentes de outros produtos AEM. O tutorial destaca diferenças e considerações especiais ao desenvolver para AEM Screens.
Este tutorial destina-se a desenvolvedores que são novos na AEM Screens. Neste tutorial, um componente simples "Hello World" é criado para um canal de sequência no AEM Screens. Uma caixa de diálogo permite que os autores atualizem o texto exibido.
Para concluir este tutorial, é necessário o seguinte:
Pacote de recursos do AEM 6.5 ou AEM 6.3 + mais recente
Ambiente de desenvolvimento local
As etapas do tutorial e as capturas de tela são executadas usando CRXDE-Lite. Os IDEs também podem ser usados para concluir o tutorial. Mais informações sobre como usar um IDE para desenvolver com AEM podem ser encontradas aqui.
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 AEM Project Archetype 13. Mais detalhes sobre criar um projeto com o Maven AEM Project Archetype podem ser encontrados aqui.
Baixe e instale os seguintes pacotes usando gerenciador de pacote CRX:
Obter arquivo
Como opção, se estiver trabalhando com o Eclipse ou outro IDE, baixe o pacote de origem abaixo. Implante o projeto para uma instância AEM local usando o comando Maven:
mvn -PautoInstallPackage clean install
Start HelloWorld SRC Screens We.Retail Run Project
Em CRX Package Manager, verifique se os dois pacotes a seguir estão instalados:
Screens We.Retail Run Ui.Apps e Pacotes Ui.Content instalados pelo CRX Package Manager
O pacote screens-weretail-run.ui.apps instala o código abaixo de /apps/weretail-run
.
Este pacote contém o código responsável pela renderização de componentes personalizados para o 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.
Neste tutorial, nenhum código Java é gravado. Se for necessária uma lógica comercial mais complexa, o Java de back-end poderá ser criado e implantado usando o pacote Java principal.
Representação do código ui.apps no CRXDE Lite
O componente helloworld é atualmente apenas um espaço reservado. Durante o curso do tutorial, a funcionalidade será adicionada, permitindo que o autor atualize a mensagem exibida pelo componente.
O pacote screens-weretail-run.ui.content instala o código abaixo:
/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 para o projeto We.Retail Run. /content/dam/we-retail-run
inclui o início de ativos digitais para o projeto. /content/screens/we-retail-run
contém a estrutura de conteúdo do Screens. O conteúdo abaixo de todos esses caminhos é atualizado principalmente em AEM. Para promover a consistência entre ambientes (local, Dev, Stage, Prod), geralmente uma estrutura de conteúdo base é salva no controle de origem.
Navegue até o projeto AEM Screens > Execução We.Retail:
No menu Start AEM > Clique no ícone Telas. Verifique se o projeto We.Retail Run (Execução do We.Retail) pode ser visto.
O componente Hello World é um componente simples que permite que um usuário insira uma mensagem para ser exibida na tela. O componente se baseia no Modelo de Componente do AEM Screens: https://github.com/Adobe-Marketing-Cloud/aem-screens-component-template.
A AEM Screens tem algumas restrições interessantes que não são necessariamente verdadeiras para os componentes tradicionais do WCM Sites.
Em 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 ao componente helloworld
:
jcr:title="Hello World"
sling:resourceSuperType="foundation/components/parbase"
componentGroup="We.Retail Run - Content"
Propriedades para /apps/weretail-run/components/content/helloworld
O componente helloworld estende o componente Foundation/components/parbase para que possa ser usado corretamente dentro de um canal de sequência.
Crie um arquivo sob /apps/weretail-run/components/content/helloworld
chamado 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 da tela exigem duas renderizações diferentes, dependendo do modo de criação que está sendo usado:
helloworld.html
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 pelos componentes de tela é ter um script edit.html
para o modo de edição e um script production.html
para o modo de produção.
Crie um arquivo sob /apps/weretail-run/components/content/helloworld
chamado 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 do componente Hello World. Um atributo data-duration
é incluído, pois o componente é usado em um canal de Sequência. O atributo data-duration
é usado pelo canal de sequência para saber por quanto tempo um item de sequência deve ser exibido.
O componente renderiza uma tag div
e 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 o texto da propriedade message
.
Observe também que a notação BEM (Block Element Modifier) é usada com o componente. O BEM é uma convenção de codificação de CSS que facilita a criação de componentes reutilizáveis. BEM é a notação usada por AEM Componentes principais. Mais informações podem ser encontradas em: https://getbem.com/
Crie um arquivo sob /apps/weretail-run/components/content/helloworld
chamado 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 será renderizado se nenhuma mensagem de diálogo tiver sido inserida. Os cq-placeholder
e data-emptytext
renderizam o rótulo Hello World como espaço reservado nesse caso. A string para o rótulo pode ser internacionalizada usando o i18n para oferecer suporte à criação em várias localidades.
Caixa de diálogo Copiar imagem da tela a ser usada para o componente Hello World.
É mais fácil start de uma caixa de diálogo existente e fazer modificações.
/libs/screens/core/components/content/image/cq:dialog
/apps/weretail-run/components/content/helloworld
Atualize a caixa de diálogo Hello World para incluir uma guia para a mensagem.
Atualize a caixa de diálogo para que ela 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 o campo de número para Duração será salvo em uma propriedade chamada duration
. Essas duas propriedades são referenciadas em /apps/weretail-run/components/content/helloworld/production.html
por HTL como ${properties.message}
e ${properties.duration}
.
Hello World - diálogo concluído
As bibliotecas do lado do cliente fornecem um mecanismo para organizar e gerenciar arquivos CSS e JavaScript necessários para uma implementação AEM.
Os componentes do AEM Screens são renderizados de forma diferente no modo de edição vs. Pré-visualização/produção. Duas bibliotecas clientes serão criadas, uma para o modo de edição e outra para a Pré-visualização/produção.
Crie uma pasta para bibliotecas do lado do cliente para o componente Hello World.
Abaixo de /apps/weretail-run/components/content/helloworld
crie uma nova pasta chamada clientlibs
.
Abaixo da pasta clientlibs
crie um novo nó chamado shared
do tipo cq:ClientLibraryFolder.
Adicione as seguintes propriedades à biblioteca de clientes compartilhados:
allowProxy
| Booleano | true
categories
| String[] | cq.screens.components
Propriedades para /apps/weretail-run/components/content/helloworld/clientlibs/shared
A propriedade categoria é uma string que identifica a biblioteca do cliente. A categoria cq.screens.components é usada nos modos Editar e Pré-visualização/Produção. Portanto, qualquer CSS/JS definido no Shahdclientlib é 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 a biblioteca do cliente CSS e JS sejam referenciadas por meio de um prefixo of/etc.clientlibs.
Crie um arquivo chamado css.txt
abaixo da pasta compartilhada.
Preencha o arquivo com o seguinte:
#base=css
styles.less
Crie uma pasta chamada css
abaixo da pasta shared
. Adicione um arquivo chamado style.less
abaixo da pasta css
. A estrutura das bibliotecas de clientes agora deve ser parecida com esta:
Em vez de gravar CSS diretamente, este tutorial usa MENOS. O LESS é um pré-compilador de CSS popular que suporta variáveis, mixins e funções de CSS. AEM bibliotecas de clientes oferecem suporte nativo para a compilação LESS. É possível usar Sass ou outros pré-compiladores, mas eles precisam ser compilados fora do AEM.
Preencha /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;
}
}
Copie e cole a pasta da biblioteca do cliente shared
para criar uma nova biblioteca do cliente chamada production
.
Copie a biblioteca de cliente compartilhado para criar uma nova biblioteca de cliente de produção
Atualize a propriedade categories
da biblioteca de cliente de produção para cq.screens.components.production.
Isso garante que os estilos sejam carregados somente no modo Pré-visualização/Produção.
Propriedades para /apps/weretail-run/components/content/helloworld/clientlibs/production
Preencha /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 da biblioteca de clientes: cq.screens.components.edit
poderia ser usado para adicionar estilos específicos somente para edição ao componente.
Categoria Clientlib | Uso |
---|---|
cq.screens.components |
Estilos e scripts que são compartilhados entre os modos de edição e produção |
cq.screens.components.edit |
Estilos e scripts usados somente no modo de edição |
cq.screens.components.production |
Estilos e scripts que são usados apenas no modo de produção |
A 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 os componentes permitidos para o Parsys em um canal. A prática recomendada é armazenar essas configurações de uma maneira específica para o aplicativo.
Abaixo de uma página We.Retail Run Design é criada e armazenará todas as configurações específicas do projeto We.Retail Run.
Em CRXDE-Lite http://localhost:4502/crx/de/index.jsp#/apps/settings/wcm/designs
, navegue até /apps/settings/wcm/designs
Crie um novo nó abaixo da pasta de designs, chamado we-retail-run
com um tipo de cq:Page
.
Abaixo da página we-retail-run
, adicione outro nó chamado jcr:content
do tipo nt:unstructured
. Adicione as seguintes propriedades ao nó jcr:content
:
Nome | Tipo | Valor |
---|---|---|
jcr:title | Sequência de caracteres | Execução We.Retail |
sling:resourceType | Sequência de caracteres | wcm/core/components/designer |
cq:doctype | Sequência de caracteres | html_5 |
Página de design em /apps/settings/wcm/designs/we-retail-run
O componente Hello World deve ser usado em um Canal de sequência. Para testar o componente, um novo Canal de Sequência é criado.
No Menu de Start AEM, navegue até Screens > We.Retail Ru n > e selecione Canais.
Clique no botão Criar
No assistente Criar:
Etapa do modelo - escolha Canal de sequência
Abra as propriedades de página do Canal Inativo. 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 apontando para /apps/settings/wcm/designs/we-retail-run
Edite o Canal inativo recém-criado para abri-lo.
Alternar o modo de página para Modo Design
Clique no ícone chave no Parsys para configurar os componentes permitidos
Selecione o grupo Screens e o grupo Execução We.Retail - Content.
Alterne 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.
Em 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 que a propriedade components
agora inclui group:Screens
, group:We.Retail Run - Content
.
Configuração de design em /apps/settings/wcm/designs/we-retail-run
Caso seu componente personalizado esteja usando recursos externos, como ativos (imagens, vídeos, fontes, ícones, etc.), representações de ativos específicos ou bibliotecas do lado do cliente (css, js etc.), eles não são adicionados automaticamente à configuração offline, pois apenas agrupamos a marcação HTML por padrão.
Para permitir que você personalize e otimize os ativos exatos que são baixados para o player, ofertas um mecanismo de extensão para que os componentes personalizados exponham suas dependências à lógica de cache offline no Screens.
A seção abaixo mostra o modelo para manipuladores de recursos offline personalizados e os requisitos mínimos em 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 em 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>
O vídeo abaixo mostra o componente finalizado e como ele pode ser adicionado a um canal de sequência. O Canal é então adicionado a uma tela Local e, por fim, atribuído a um player do Screens.
Abaixo está o código finalizado do tutorial. Os 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 AEM compilados. O SRC-screens-weretail-run-0.0.1.zip é o código fonte não compilado que pode ser implantado usando o Maven.