Creare un componente meteo personalizzato custom-component
Scopri come creare un componente meteo personalizzato da utilizzare con l’Editor SPA dell’AEM. Scopri come sviluppare finestre di dialogo di authoring e modelli Sling per estendere il modello JSON e popolare un componente personalizzato. Vengono utilizzati Open Weather API e React Open Weather Component.
Obiettivo
- Comprendi il ruolo dei modelli Sling nella manipolazione dell’API del modello JSON fornita dall’AEM.
- Scopri come creare nuove finestre di dialogo per i componenti dell’AEM.
- Scopri come creare un componente AEM personalizzato compatibile con il framework dell’editor SPA.
Cosa verrà creato
Viene creato un semplice componente meteo. Questo componente può essere aggiunto all’SPA dagli autori di contenuti. Utilizzando una finestra di dialogo dell’AEM, gli autori possono impostare la posizione in cui visualizzare il meteo. L’implementazione di questo componente illustra i passaggi necessari per creare un nuovo componente AEM compatibile con il framework dell’Editor SPA dell’AEM.
Prerequisiti
Esaminare gli strumenti e le istruzioni necessari per configurare un ambiente di sviluppo locale. Questo capitolo è una continuazione del capitolo Navigazione e instradamento, tuttavia a seguire tutto ciò che serve è un progetto AEM abilitato per SPA distribuito a un'istanza AEM locale.
Apri chiave API meteo
È necessaria una chiave API di Open Weather per seguire l'esercitazione. La registrazione è gratuita per un numero limitato di chiamate API.
Definire il componente AEM
Un componente AEM è definito come nodo e proprietà. Nel progetto questi nodi e proprietà sono rappresentati come file XML nel modulo ui.apps
. Creare quindi il componente AEM nel modulo ui.apps
.
-
Nell'IDE scelto aprire la cartella
ui.apps
. -
Passare a
ui.apps/src/main/content/jcr_root/apps/wknd-spa-react/components
e creare una nuova cartella denominataopen-weather
. -
Creare un nuovo file denominato
.content.xml
sotto la cartellaopen-weather
. Popolareopen-weather/.content.xml
con quanto segue: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 che questo nodo è un componente AEM.jcr:title
è il valore visualizzato agli autori di contenuti ecomponentGroup
determina il raggruppamento di componenti nell'interfaccia utente di creazione. -
Nella cartella
custom-component
creare un'altra cartella denominata_cq_dialog
. -
Nella cartella
_cq_dialog
creare un nuovo file denominato.content.xml
e popolarlo con il seguente: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>
Il file XML sopra riportato genera una finestra di dialogo molto semplice per
Weather Component
. La parte critica del file è costituita dai nodi interni<label>
,<lat>
e<lon>
. Questa finestra di dialogo contiene duenumberfield
e untextfield
che consente a un utente di configurare il meteo da visualizzare.Accanto a è stato creato un modello Sling per esporre il valore delle proprietà
label
,lat
elong
tramite il modello JSON.note note NOTE Puoi visualizzare molti più esempi di finestre di dialogo visualizzando le definizioni dei Componenti core. Puoi anche visualizzare altri campi modulo, come select
,textarea
,pathfield
, disponibili sotto/libs/granite/ui/components/coral/foundation/form
in CRXDE-Lite.Con un componente AEM tradizionale, in genere è necessario uno script HTL. Poiché l’SPA eseguirà il rendering del componente, non è necessario alcuno script HTL.
Creare il modello Sling
I modelli Sling sono Java "POJO" (Plain Old Java Objects) basati su annotazioni che facilitano la mappatura dei dati da JCR a variabili Java. I modelli Sling in genere funzionano per incapsulare una logica di business lato server complessa per i componenti AEM.
Nel contesto dell'editor SPA, i modelli Sling espongono il contenuto di un componente tramite il modello JSON tramite una funzione che utilizza Sling Model Exporter.
-
Nell'IDE scelto aprire il modulo
core
inaem-guides-wknd-spa.react/core
. -
Creare un file denominato in
OpenWeatherModel.java
incore/src/main/java/com/adobe/aem/guides/wkndspa/react/core/models
. -
Popolare
OpenWeatherModel.java
con quanto segue: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(); }
Questa è l’interfaccia Java del nostro componente. Affinché il modello Sling sia compatibile con il framework dell'editor SPA, deve estendere la classe
ComponentExporter
. -
Creare una cartella denominata
impl
sottocore/src/main/java/com/adobe/aem/guides/wkndspa/react/core/models
. -
Creare un file denominato
OpenWeatherModelImpl.java
sottoimpl
e popolarlo come segue: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; } }
La variabile statica
RESOURCE_TYPE
deve puntare al percorso inui.apps
del componente.getExportedType()
viene utilizzato per mappare le proprietà JSON al componente SPA tramiteMapTo
.@ValueMapValue
è un'annotazione che legge la proprietà jcr salvata dalla finestra di dialogo.
Aggiornare l’SPA
Quindi, aggiornare il codice React per includere il componente Tempo aperto React e farlo mappare al componente AEM creato nei passaggi precedenti.
-
Installa il componente React Open Weather come dipendenza npm:
code language-shell $ cd aem-guides-wknd-spa.react/ui.frontend $ npm i react-open-weather
-
Creare una nuova cartella denominata
OpenWeather
inui.frontend/src/components/OpenWeather
. -
Aggiungere un file denominato
OpenWeather.js
e popolarlo con il seguente: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);
-
Aggiorna
import-components.js
alleui.frontend/src/components/import-components.js
per includere il componenteOpenWeather
:code language-diff // import-component.js import './Container/Container'; import './ExperienceFragment/ExperienceFragment'; + import './OpenWeather/OpenWeather';
-
Distribuisci tutti gli aggiornamenti a un ambiente AEM locale dalla directory principale del progetto, utilizzando le tue competenze Maven:
code language-shell $ cd aem-guides-wknd-spa.react $ mvn clean install -PautoInstallSinglePackage
Aggiornare il criterio del modello
Passare quindi all'AEM per verificare gli aggiornamenti e consentire l'aggiunta del componente OpenWeather
all'SPA.
-
Verifica la registrazione del nuovo modello Sling passando a 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'
Le due righe precedenti indicano che
OpenWeatherModelImpl
è associato al componentewknd-spa-react/components/open-weather
e che è registrato tramite Sling Model Exporter. -
Passa al modello per pagina SPA all'indirizzo http://localhost:4502/editor.html/conf/wknd-spa-react/settings/wcm/templates/spa-page-template/structure.html.
-
Aggiornare il criterio Contenitore di layout per aggiungere il nuovo
Open Weather
come componente consentito:Salvare le modifiche al criterio e osservare
Open Weather
come componente consentito:
Creare il componente Tempo aperto
Creare quindi il componente Open Weather
utilizzando l'editor SPA dell'AEM.
-
Passa a http://localhost:4502/editor.html/content/wknd-spa-react/us/en/home.html.
-
In modalità
Edit
, aggiungereOpen Weather
aLayout Container
: -
Apri la finestra di dialogo del componente e immetti un Etichetta, Latitudine e Longitudine. Ad esempio San Diego, 32.7157 e -117.1611. I numeri dell'emisfero occidentale e dell'emisfero australe sono rappresentati come numeri negativi con l'API Open Weather
Questa è la finestra di dialogo creata in base al file XML precedente nel capitolo.
-
Salva le modifiche. Osserva che il meteo per San Diego è ora visualizzato:
-
Visualizza il modello JSON passando a http://localhost:4502/content/wknd-spa-react/us/en.model.json. Cerca
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" }
I valori JSON vengono generati dal modello Sling. Questi valori JSON vengono trasmessi nel componente React come prop.
Congratulazioni. congratulations
Congratulazioni, hai imparato a creare un componente AEM personalizzato da utilizzare con l’Editor SPA. Hai anche imparato come le finestre di dialogo, le proprietà JCR e i modelli Sling interagiscono per generare il modello JSON.
Passaggi successivi next-steps
Estendere un componente core - Scopri come estendere un componente core AEM esistente da utilizzare con l'editor SPA dell'AEM. Comprendere come aggiungere proprietà e contenuti a un componente esistente è una tecnica efficace per espandere le funzionalità di un’implementazione dell’Editor SPA dell’AEM.