Criar um componente de clima personalizado custom-component
Saiba como criar um componente de clima personalizado para ser usado com o Editor de SPA AEM. Saiba como desenvolver caixas de diálogo de criação e Modelos Sling para estender o modelo JSON e preencher um componente personalizado. A API de Clima Aberto e o componente de Clima Aberto do React são usados.
Objetivo
- Entenda a função dos Modelos do Sling na manipulação da API do modelo JSON fornecida pelo AEM.
- Entenda como criar caixas de diálogo do novo componente AEM.
- Saiba como criar um Componente de AEM personalizado que seja compatível com a estrutura do editor de SPA.
O que você vai criar
Um componente meteorológico simples é construído. Esse componente pode ser adicionado ao SPA por autores de conteúdo. Usando uma caixa de diálogo AEM, os autores podem definir o local para a exibição do tempo. A implementação deste componente ilustra as etapas necessárias para criar um novo componente de AEM que seja compatível com a estrutura do Editor de SPA do AEM.
Pré-requisitos
Revise as ferramentas e instruções necessárias para configurar um ambiente de desenvolvimento local. Este capítulo é uma continuação do capítulo Navegação e Roteamento. No entanto, basta seguir um projeto AEM habilitado para SPA implantado em uma instância AEM local para que você precise seguir.
Abrir chave de API do clima
Uma chave de API do Tempo Aberto é necessária para acompanhar o tutorial. A inscrição é gratuita para uma quantidade limitada de chamadas de API.
Definir o componente AEM
Um componente AEM é definido como um nó e propriedades. No projeto, esses nós e propriedades são representados como arquivos XML no módulo ui.apps
. Em seguida, crie o componente AEM no módulo ui.apps
.
-
No IDE de sua escolha, abra a pasta
ui.apps
. -
Navegue até
ui.apps/src/main/content/jcr_root/apps/wknd-spa-react/components
e crie uma nova pasta chamadaopen-weather
. -
Crie um novo arquivo chamado
.content.xml
abaixo da pastaopen-weather
. Preencha oopen-weather/.content.xml
com o seguinte: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="Open Weather" componentGroup="WKND SPA React - Content"/>
jcr:primaryType="cq:Component"
- identifica que este nó é um componente AEM.jcr:title
é o valor exibido para os Autores de Conteúdo ecomponentGroup
determina o agrupamento de componentes na interface de criação. -
Abaixo da pasta
custom-component
, crie outra pasta chamada_cq_dialog
. -
Abaixo da pasta
_cq_dialog
, crie um novo arquivo chamado.content.xml
e preencha-o com o seguinte:code language-xml <?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" jcr:primaryType="nt:unstructured" jcr:title="Open Weather" sling:resourceType="cq/gui/components/authoring/dialog"> <content jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/container"> <items jcr:primaryType="nt:unstructured"> <tabs jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/tabs" maximized="{Boolean}true"> <items jcr:primaryType="nt:unstructured"> <properties jcr:primaryType="nt:unstructured" jcr:title="Properties" sling:resourceType="granite/ui/components/coral/foundation/container" margin="{Boolean}true"> <items jcr:primaryType="nt:unstructured"> <columns jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns" margin="{Boolean}true"> <items jcr:primaryType="nt:unstructured"> <column jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/container"> <items jcr:primaryType="nt:unstructured"> <label jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/textfield" fieldDescription="The label to display for the component" fieldLabel="Label" name="./label"/> <lat jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/numberfield" fieldDescription="The latitude of the location." fieldLabel="Latitude" step="any" name="./lat" /> <lon jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/numberfield" fieldDescription="The longitude of the location." fieldLabel="Longitude" step="any" name="./lon"/> </items> </column> </items> </columns> </items> </properties> </items> </tabs> </items> </content> </jcr:root>
O arquivo XML acima gera uma caixa de diálogo muito simples para
Weather Component
. A parte crítica do arquivo são os nós internos<label>
,<lat>
e<lon>
. Esta caixa de diálogo contém doisnumberfield
s e umtextfield
que permite que um usuário configure o tempo a ser exibido.Um Modelo Sling é criado próximo a expor o valor das propriedades
label
,lat
elong
por meio do modelo JSON.note note NOTE Você pode exibir muito mais exemplos de caixas de diálogo ao exibir as definições dos Componentes principais. Você também pode exibir campos de formulário adicionais, como select
,textarea
,pathfield
, disponíveis em/libs/granite/ui/components/coral/foundation/form
no CRXDE-Lite.Com um componente AEM tradicional, geralmente é necessário um script HTL. Como o SPA renderizará o componente, nenhum script HTL é necessário.
Criar o modelo do Sling
Os Modelos do Sling são objetos POJO (Plain Old Java Objects) orientados por anotações que facilitam o mapeamento de dados do JCR para variáveis Java. Os Modelos Sling geralmente funcionam para encapsular uma lógica comercial complexa do lado do servidor para Componentes AEM.
No contexto do Editor de SPA, os Modelos Sling expõem o conteúdo de um componente por meio do modelo JSON por meio de um recurso que usa o Exportador de Modelo Sling.
-
No IDE de sua escolha, abra o módulo
core
emaem-guides-wknd-spa.react/core
. -
Crie um arquivo com o nome em
OpenWeatherModel.java
emcore/src/main/java/com/adobe/aem/guides/wkndspa/react/core/models
. -
Popular
OpenWeatherModel.java
com o seguinte:code language-java package com.adobe.aem.guides.wkndspa.react.core.models; import com.adobe.cq.export.json.ComponentExporter; // Sling Models intended to be used with SPA Editor must extend ComponentExporter interface public interface OpenWeatherModel extends ComponentExporter { public String getLabel(); public double getLat(); public double getLon(); }
Esta é a interface Java do nosso componente. Para que nosso Modelo Sling seja compatível com a estrutura do Editor de SPA, ele deve estender a classe
ComponentExporter
. -
Crie uma pasta chamada
impl
abaixo decore/src/main/java/com/adobe/aem/guides/wkndspa/react/core/models
. -
Crie um arquivo com o nome
OpenWeatherModelImpl.java
abaixo deimpl
e preencha com o seguinte:code language-java package com.adobe.aem.guides.wkndspa.react.core.models.impl; import org.apache.sling.models.annotations.*; import org.apache.sling.models.annotations.injectorspecific.ValueMapValue; import com.adobe.cq.export.json.ComponentExporter; import com.adobe.cq.export.json.ExporterConstants; import org.apache.commons.lang3.StringUtils; import org.apache.sling.api.SlingHttpServletRequest; import com.adobe.aem.guides.wkndspa.react.core.models.OpenWeatherModel; // Sling Model annotation @Model( adaptables = SlingHttpServletRequest.class, adapters = { OpenWeatherModel.class, ComponentExporter.class }, resourceType = OpenWeatherModelImpl.RESOURCE_TYPE, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL ) @Exporter( //Exporter annotation that serializes the modoel as JSON name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION ) public class OpenWeatherModelImpl implements OpenWeatherModel { @ValueMapValue private String label; //maps variable to jcr property named "label" persisted by Dialog @ValueMapValue private double lat; //maps variable to jcr property named "lat" @ValueMapValue private double lon; //maps variable to jcr property named "lon" // points to AEM component definition in ui.apps static final String RESOURCE_TYPE = "wknd-spa-react/components/open-weather"; // public getter method to expose value of private variable `label` // adds additional logic to default the label to "(Default)" if not set. @Override public String getLabel() { return StringUtils.isNotBlank(label) ? label : "(Default)"; } // public getter method to expose value of private variable `lat` @Override public double getLat() { return lat; } // public getter method to expose value of private variable `lon` @Override public double getLon() { return lon; } // method required by `ComponentExporter` interface // exposes a JSON property named `:type` with a value of `wknd-spa-react/components/open-weather` // required to map the JSON export to the SPA component props via the `MapTo` @Override public String getExportedType() { return OpenWeatherModelImpl.RESOURCE_TYPE; } }
A variável estática
RESOURCE_TYPE
deve apontar para o caminho emui.apps
do componente. OgetExportedType()
é usado para mapear as propriedades JSON para o componente SPA viaMapTo
.@ValueMapValue
é uma anotação que lê a propriedade jcr salva pelo diálogo.
Atualizar o SPA
Em seguida, atualize o código do React para incluir o componente de Tempo Aberto do React e mapeie-o para o componente AEM criado nas etapas anteriores.
-
Instalar o componente de clima aberto do React como uma dependência de npm:
code language-shell $ cd aem-guides-wknd-spa.react/ui.frontend $ npm i react-open-weather
-
Crie uma nova pasta chamada
OpenWeather
emui.frontend/src/components/OpenWeather
. -
Adicione um arquivo chamado
OpenWeather.js
e preencha-o com o seguinte:code language-js import React from 'react'; import {MapTo} from '@adobe/aem-react-editable-components'; import ReactWeather, { useOpenWeather } from 'react-open-weather'; // Open weather API Key // For simplicity it is hard coded in the file, ideally this is extracted in to an environment variable const API_KEY = 'YOUR_API_KEY'; // Logic to render placeholder or component const OpenWeatherEditConfig = { emptyLabel: 'Weather', isEmpty: function(props) { return !props || !props.lat || !props.lon || !props.label; } }; // Wrapper function that includes react-open-weather component function ReactWeatherWrapper(props) { const { data, isLoading, errorMessage } = useOpenWeather({ key: API_KEY, lat: props.lat, // passed in from AEM JSON lon: props.lon, // passed in from AEM JSON lang: 'en', unit: 'imperial', // values are (metric, standard, imperial) }); return ( <div className="cmp-open-weather"> <ReactWeather isLoading={isLoading} errorMessage={errorMessage} data={data} lang="en" locationLabel={props.label} // passed in from AEM JSON unitsLabels={{ temperature: 'F', windSpeed: 'mph' }} showForecast={false} /> </div> ); } export default function OpenWeather(props) { // render nothing if component not configured if (OpenWeatherEditConfig.isEmpty(props)) { return null; } // render ReactWeather component if component configured // pass props to ReactWeatherWrapper. These props include the mapped properties from AEM JSON return ReactWeatherWrapper(props); } // Map OpenWeather to AEM component MapTo('wknd-spa-react/components/open-weather')(OpenWeather, OpenWeatherEditConfig);
-
Atualize
import-components.js
emui.frontend/src/components/import-components.js
para incluir o componenteOpenWeather
:code language-diff // import-component.js import './Container/Container'; import './ExperienceFragment/ExperienceFragment'; + import './OpenWeather/OpenWeather';
-
Implante todas as atualizações em um ambiente AEM local da raiz do diretório do projeto, usando suas habilidades em Maven:
code language-shell $ cd aem-guides-wknd-spa.react $ mvn clean install -PautoInstallSinglePackage
Atualizar a política do modelo
Em seguida, navegue até AEM para verificar as atualizações e permitir que o componente OpenWeather
seja adicionado ao SPA.
-
Verifique o registro do novo Modelo do Sling navegando até http://localhost:4502/system/console/status-slingmodels.
code language-plain com.adobe.aem.guides.wkndspa.react.core.models.impl.OpenWeatherModelImpl - wknd-spa-react/components/open-weather com.adobe.aem.guides.wkndspa.react.core.models.impl.OpenWeatherModelImpl exports 'wknd-spa-react/components/open-weather' with selector 'model' and extension '[Ljava.lang.String;@2fd80fc5' with exporter 'jackson'
Você deve ver as duas linhas acima que indicam que
OpenWeatherModelImpl
está associado ao componentewknd-spa-react/components/open-weather
e que ele está registrado por meio do Exportador de Modelo do Sling. -
Navegue até o Modelo de página SPA em http://localhost:4502/editor.html/conf/wknd-spa-react/settings/wcm/templates/spa-page-template/structure.html.
-
Atualize a política do Contêiner de Layout para adicionar o novo
Open Weather
como um componente permitido:Salve as alterações na política e observe o
Open Weather
como um componente permitido:
Criar o componente de Tempo aberto
Em seguida, crie o componente Open Weather
usando o Editor SPA AEM.
-
Navegue até http://localhost:4502/editor.html/content/wknd-spa-react/us/en/home.html.
-
No modo
Edit
, adicione oOpen Weather
aoLayout Container
: -
Abra a caixa de diálogo do componente e insira um Rótulo, Latitude e Longitude. Por exemplo San Diego, 32.7157 e -117.1611. Os números do hemisfério ocidental e do hemisfério sul são representados como números negativos com a API de Tempo Aberto
Esta é a caixa de diálogo que foi criada com base no arquivo XML mencionado anteriormente no capítulo.
-
Salve as alterações. Observe que o tempo para San Diego agora é exibido:
-
Exiba o modelo JSON navegando até http://localhost:4502/content/wknd-spa-react/us/en.model.json. Pesquisar por
wknd-spa-react/components/open-weather
:code language-json "open_weather": { "label": "San Diego", "lat": 32.7157, "lon": -117.1611, ":type": "wknd-spa-react/components/open-weather" }
Os valores JSON são gerados pelo Modelo Sling. Esses valores JSON são passados para o componente React como props.
Parabéns. congratulations
Parabéns, você aprendeu a criar um componente personalizado do AEM para ser usado com o Editor de SPA. Você também aprendeu como caixas de diálogo, propriedades JCR e Modelos Sling interagem para produzir o modelo JSON.
Próximas etapas next-steps
Estender um Componente Principal - Saiba como estender um Componente Principal do AEM existente para ser usado com o Editor de SPA do AEM. AEM Entender como adicionar propriedades e conteúdo a um componente existente é uma técnica poderosa para expandir os recursos de uma implementação do Editor de SPA.