Creare un’app React con le API OpenAPI di distribuzione dei frammenti di contenuto di AEM
In questo capitolo, scopri come la distribuzione di frammenti di contenuto di AEM con API OpenAPI può stimolare l’esperienza in applicazioni esterne.
Viene utilizzata una semplice app React per richiedere e visualizzare il contenuto di Team e Persona esposto da AEM Content Fragment Delivery con API OpenAPI. L’utilizzo di React è in gran parte irrilevante e l’applicazione esterna che ne usufruisce può essere scritta in qualsiasi framework per qualsiasi piattaforma, purché possa effettuare richieste HTTP ad AEM as a Cloud Service.
Prerequisiti
Si presume che i passaggi descritti nelle parti precedenti di questo tutorial in più parti siano stati completati.
È necessario installare il seguente software:
Obiettivi
Scopri come:
- Scarica e avvia l’app React di esempio.
- Richiama AEM Content Fragment Delivery con API OpenAPI per un elenco di team e dei relativi membri di riferimento.
- Richiama Consegna di frammenti di contenuto di AEM con API OpenAPI per recuperare i dettagli di un membro del team.
Configurare CORS su AEM as a Cloud Service
Questo esempio di app React viene eseguita localmente (su http://localhost:3000) e si connette alla distribuzione di frammenti di contenuto AEM del servizio di pubblicazione di AEM con API OpenAPI. Per consentire questa connessione, è necessario configurare CORS (Cross-Origin Resource Sharing) nel servizio AEM Publish (o Anteprima).
Proxy CORS locale
In alternativa, per lo sviluppo, esegui un proxy CORS locale che consente una connessione compatibile con CORS ad AEM.
$ npm install --global lcp
$ lcp --proxyUrl https://publish-p<PROGRAM_ID>-e<ENVIRONMENT_ID>.adobeaemcloud.com
Aggiorna il valore --proxyUrl nell'URL di pubblicazione (o anteprima) di AEM.
Con il proxy CORS locale in esecuzione, accedi alle API di distribuzione dei frammenti di contenuto di AEM all'indirizzo http://localhost:8010/proxy per evitare problemi CORS.
Clonare l’app React di esempio
Un esempio di app React sottoposta a stubbed-out viene implementata con il codice necessario per interagire con AEM Content Fragment Delivery (Distribuzione di frammenti di contenuto) con le API OpenAPI e visualizzare i dati di team e persone ottenuti da queste.
Il codice sorgente dell'app React di esempio è disponibile su Github.com.
Per ottenere l’app React:
-
Clona l'app WKND OpenAPI React di esempio da Github.com dal tag
headless_open-api_basic.code language-shell $ cd ~/Code $ git clone git@github.com:adobe/aem-tutorials.git $ cd aem-tutorials $ git fetch --tags $ git tag $ git checkout tags/headless_open-api_basic -
Passare alla cartella
headless/open-api/basice aprirla nell'IDE.code language-shell $ cd ~/Code/aem-tutorials/headless/open-api/basic $ code . -
Aggiorna
.envper connetterti al servizio AEM as a Cloud Service Publish, dove vengono pubblicati i frammenti di contenuto. Questo può indicare il servizio di anteprima di AEM se desideri testare l’app con il servizio di anteprima di AEM (e i frammenti di contenuto vengono pubblicati lì).code language-none # AEM Publish (or Preview) service that provides Content Fragments REACT_APP_HOST_URI=https://publish-p123-e456.adobeaemcloud.comQuando si utilizza Local CORS Proxy, impostare
REACT_APP_HOST_URIsuhttp://localhost:8010/proxy.code language-none # AEM Publish (or Preview) service that provides Content Fragments REACT_APP_HOST_URI=http://localhost:8010/proxy -
Avviare l’app React
code language-shell $ cd ~/Code/aem-tutorials/headless/open-api/basic $ npm install $ npm start -
L'app React viene avviata in modalità di sviluppo il http://localhost:3000/. Le modifiche apportate all’app React durante l’esercitazione vengono immediatamente riportate nel browser web.
> // TODO: implementalo seguendo i passaggi dell’esercitazione AEM Headless
> // *****************************
Anatomia dell’app React
L’app React di esempio ha tre parti principali che richiedono l’aggiornamento.
- Il file
.envcontiene l'URL del servizio di pubblicazione (o anteprima) di AEM. src/components/Teams.jsvisualizza un elenco di team e dei relativi membri.src/components/Person.jsvisualizza i dettagli di un singolo membro del team.
Implementare le funzionalità dei team
Crea la funzionalità per visualizzare i team e i relativi membri nella visualizzazione principale dell’app React. Questa funzionalità richiede:
- Nuovo hook useEffect personalizzato di React che richiama l'API List all Content Fragments tramite una richiesta di recupero e quindi ottiene il valore
fullNameper ogniteamMemberper la visualizzazione.
Una volta completata, la vista principale dell’app si popola con i dati dei team provenienti da AEM.
-
Apri
src/components/Teams.js. -
Implementa il componente Team per recuperare l'elenco dei team da Elenca tutte le API dei frammenti di contenuto ed eseguire il rendering del contenuto dei team. Questa procedura è suddivisa nei seguenti passaggi:
-
Crea un hook
useEffectche richiama l'API List all Content Fragments di AEM e memorizza i dati nello stato del componente React. -
Per ogni frammento di contenuto Team restituito, richiama l'API Get a Content Fragment per recuperare i dettagli completi del team, inclusi i membri e i relativi
fullNames. -
Eseguire il rendering dei dati dei team utilizzando la funzione
Team.code language-javascript import { useEffect, useState } from "react"; import { Link } from "react-router-dom"; import "./Teams.scss"; function Teams() { // The teams folder is the only folder-tree that is allowed to contain Team Content Fragments. const TEAMS_FOLDER = '/content/dam/my-project/en/teams'; // State to store the teams data const [teams, setTeams] = useState(null); useEffect(() => { /** * Fetches all teams and their associated member details * This is a two-step process: * 1. First, get all team content fragments from the specified folder * 2. Then, for each team, fetch the full details including hydrated references to get the team member names */ const fetchData = async () => { try { // Step 1: Fetch all teams from the teams folder const response = await fetch( `${process.env.REACT_APP_HOST_URI}/adobe/contentFragments?path=${TEAMS_FOLDER}` ); const allTeams = (await response.json()).items || []; // Step 2: Fetch detailed information for each team with hydrated references const hydratedTeams = []; for (const team of allTeams) { const hydratedTeamResponse = await fetch( `${process.env.REACT_APP_HOST_URI}/adobe/contentFragments/${team.id}?references=direct-hydrated` ); hydratedTeams.push(await hydratedTeamResponse.json()); } setTeams(hydratedTeams); } catch (error) { console.error("Error fetching content fragments:", error); } }; fetchData(); }, [TEAMS_FOLDER]); // Show loading state while teams data is being fetched if (!teams) { return <div>Loading teams...</div>; } // Render the teams return ( <div className="teams"> {teams.map((team, index) => { return ( <Team key={index} {..team} /> ); })} </div> ); } /** * Team component - renders a single team with its details and members * @param {string} fields - The authorable fields * @param {Object} references - Hydrated references containing member details such as fullName */ function Team({ fields, references, path }) { if (!fields.title || !fields.teamMembers) { return null; } return ( <div className="team"> <h2 className="team__title">{fields.title}</h2> {/* Render description as HTML using dangerouslySetInnerHTML */} <p className="team__description" dangerouslySetInnerHTML={{ __html: fields.description.value }} /> <div> <h4 className="team__members-title">Members</h4> <ul className="team__members"> {/* Render each team member as a link to their detail page */} {fields.teamMembers.map((teamMember, index) => { return ( <li key={index} className="team__member"> <Link to={`/person/${teamMember}`}> {/* Display the full name from the hydrated reference */} {references[teamMember].value.fields.fullName} </Link> </li> ); })} </ul> </div> </div> ); } export default Teams;
Implementare la funzionalità della persona
Quando la funzionalità Team è stata completata, implementare la funzionalità per gestire la visualizzazione dei dettagli di un membro del team o di una persona.
Per effettuare questo collegamento:
-
Apri
src/components/Person.js -
Nel componente React
Person, analizzare il parametro routeid. Si noti che le route dell'app React sono state precedentemente impostate per accettare il parametro URLid(vedere/src/App.js). -
Recupera i dati della persona da AEM con l'API Get Content Fragment.
code language-javascript import "./Person.scss"; import { useEffect, useState } from "react"; import { useParams } from "react-router-dom"; /** * Person component - displays detailed information about a single person * Fetches person data from AEM using the ID from the URL parameters */ function Person() { // Get the person ID from the URL parameter const { id } = useParams(); // State to store the person data const [person, setPerson] = useState(null); useEffect(() => { /** * Fetches person data from AEM Content Fragment Delivery API * Uses the ID from URL parameters to get the specific person's details */ const fetchData = async () => { try { /* Hydrate references for access to profilePicture asset path */ const response = await fetch( `${process.env.REACT_APP_HOST_URI}/adobe/contentFragments/${id}?references=direct-hydrated` ); const json = await response.json(); setPerson(json || null); } catch (error) { console.error("Error fetching person data:", error); } }; fetchData(); }, [id]); // Re-fetch when ID changes // Show loading state while person data is being fetched if (!person) { return <div>Loading person...</div>; } return ( <div className="person"> {/* Person profile image - Look up the profilePicture reference in the references object */} <img className="person__image" src={process.env.REACT_APP_HOST_URI + person.references[person.fields.profilePicture].value.path} alt={person.fields.fullName} /> {/* Display person's occupations */} <div className="person__occupations"> {person.fields.occupation.map((occupation, index) => { return ( <span key={index} className="person__occupation"> {occupation} </span> ); })} </div> {/* Person's main content: name and biography */} <div className="person__content"> <h1 className="person__full-name">{person.fields.fullName}</h1> {/* Render biography as HTML content */} <div className="person__biography" dangerouslySetInnerHTML={{ __html: person.fields.biographyText.value }} /> </div> </div> ); } export default Person;
Ottieni il codice completato
Il codice sorgente completo per questo capitolo è disponibile su Github.com.
$ git fetch --tags
$ git tag
$ git checkout tags/headless_open-api_basic_4-end
Prova l’app
Rivedi l'app http://localhost:3000/ e fai clic sui collegamenti Membro del team. Inoltre, puoi aggiungere più team e/o membri al Team Alpha aggiungendo Frammenti di contenuto nel servizio AEM Author e pubblicandoli.
Dietro le quinte
Apri la console Strumenti per sviluppatori > Rete del browser e Filtra per /adobe/contentFragments richieste di recupero mentre interagisci con l'app React.
Congratulazioni.
Congratulazioni Hai creato correttamente un’app React per utilizzare e visualizzare frammenti di contenuto da Distribuzione di frammenti di contenuto di AEM con API OpenAPI.