Adicionar widgets ao Rich Text Editor (RTE)
Saiba como adicionar widgets ao Editor de Rich Text (RTE) no Editor de fragmento de conteúdo do AEM.
Para adicionar o conteúdo dinâmico no Editor de Rich Text (RTE), a funcionalidade widgets pode ser usada. Os widgets ajudam a integrar a interface de usuário simples ou complexa no RTE e a interface de usuário pode ser criada usando a estrutura JS de sua escolha. Elas podem ser consideradas como caixas de diálogo abertas ao pressionar a tecla especial {
no RTE.
Normalmente, os widgets são usados para inserir o conteúdo dinâmico que tem uma dependência de sistema externa ou que pode mudar com base no contexto atual.
Os widgets são adicionados ao RTE no Editor de Fragmento de Conteúdo usando o ponto de extensão rte
. Um ou vários widgets são adicionados usando o método getWidgets()
do ponto de extensão rte
. Eles são acionados ao pressionar a tecla especial {
para abrir a opção de menu de contexto e, em seguida, selecionar o widget desejado para carregar a interface de diálogo personalizada.
Este exemplo mostra como adicionar um widget chamado Lista de códigos de desconto para localizar, selecionar e adicionar o código de desconto específico de aventura WKND em um conteúdo RTE. Esses códigos de desconto podem ser gerenciados em um sistema externo, como o Sistema Order Management (OMS), o Gerenciamento de informações do produto (PIM), um aplicativo doméstico ou uma ação Adobe AppBuilder.
Para simplificar as coisas, este exemplo usa a estrutura Adobe React Spectrum para desenvolver a interface de widget ou caixa de diálogo e o nome de aventura WKND embutido em código, dados de código de desconto.
Ponto de extensão
Este exemplo se estende ao ponto de extensão rte
para adicionar um widget ao RTE no Editor de Fragmento de Conteúdo.
Exemplo de extensão
O exemplo a seguir cria um widget Lista de códigos de desconto. Ao pressionar a tecla especial {
no RTE, o menu de contexto é aberto e, em seguida, ao selecionar a opção Lista de Códigos de Desconto no menu de contexto, a interface do usuário da caixa de diálogo é aberta.
Os autores de conteúdo da WKND podem encontrar, selecionar e adicionar o código de desconto específico do Adventure atual, se disponível.
Registro de extensão
ExtensionRegistration.js
, mapeado para a rota index.html, é o ponto de entrada para a extensão AEM e define:
- A definição do widget na função
getWidgets()
comid, label and url
atributos. - O valor do atributo
url
, um caminho de URL relativo (/index.html#/discountCodes
) para carregar a interface do usuário da caixa de diálogo.
src/aem-cf-editor-1/web-src/src/components/ExtensionRegistration.js
import React from "react";
import { Text } from "@adobe/react-spectrum";
import { register } from "@adobe/uix-guest";
import { extensionId } from "./Constants";
// This function is called when the extension is registered with the host and runs in an iframe in the Content Fragment Editor browser window.
function ExtensionRegistration() {
const init = async () => {
const guestConnection = await register({
id: extensionId,
methods: {
rte: {
// RTE Widgets
getWidgets: () => [
{
id: "discountcode-list-widget", // Provide a unique ID for the widget
label: "Discount Code List", // Provide a label for the widget
url: "/index.html#/discountCodes", // Provide the "relative" URL to the widget content. It will be resolved as `/index.html#/discountCodes`
},
],
}, // Add a comma here
},
});
};
init().catch(console.error);
return <Text>IFrame for integration with Host (AEM)...</Text>;
}
export default ExtensionRegistration;
Adicionar rota discountCodes
em App.js
No componente principal do React App.js
, adicione a rota discountCodes
para renderizar a interface para o caminho de URL relativo acima.
src/aem-cf-editor-1/web-src/src/components/App.js
...
<Routes>
<Route index element={<ExtensionRegistration />} />
<Route
exact path="index.html"
element={<ExtensionRegistration />}
/>
{/* Content Fragment RTE routes that support the Discount Codes Widget functionality*/}
<Route path="/discountCodes" element={<DiscountCodes />} />
</Routes>
...
Criar o componente React DiscountCodes
A interface de widget ou caixa de diálogo é criada usando a estrutura Espectro de Reação Adobe. O código do componente DiscountCodes
é o seguinte: estes são os principais destaques:
- A interface é renderizada usando componentes do Espectro React, como ComboBox, ButtonGroup, Button
- A matriz
adventureDiscountCodes
tem mapeamento codificado fixo de nome de aventura e código de desconto. Em um cenário real, esses dados podem ser recuperados da ação do AppBuilder do Adobe ou de sistemas externos, como PIM, OMS ou gateway de API crescido em casa ou baseado em provedor de nuvem. - O
guestConnection
é inicializado usando ouseEffect
Gancho de reação e gerenciado como estado de componente. É usado para se comunicar com o host AEM. - A função
handleDiscountCodeChange
obtém o código de desconto para o nome de aventura selecionado e atualiza a variável de estado. - A função
addDiscountCode
que usa o objetoguestConnection
fornece instruções de RTE para execução. Neste caso, a instruçãoinsertContent
e o trecho de código HTML do código de desconto real a ser inserido no RTE.
src/aem-cf-editor-1/web-src/src/components/DiscountCodes.js
import {
Button,
ButtonGroup,
ComboBox,
Content,
Divider,
Flex, Form,
Item,
Provider,
Text,
defaultTheme
} from '@adobe/react-spectrum';
import { attach } from '@adobe/uix-guest';
import React, { useEffect, useState } from 'react';
import { extensionId } from './Constants';
const DiscountCodes = () => {
// The Adventure Discount Code list
// In this example its hard coded, however you can call an Adobe AppBuilder Action or even make an AJAX call to load it from 3rd party system
const adventureDiscountCodes = [
{ id: 1, adventureName: 'BALI SURF CAMP', discountCode: 'BALI2023' },
{ id: 2, adventureName: 'BEERVANA IN PORTLAND', discountCode: 'PORTFEST' },
{ id: 3, adventureName: 'NAPA WINE TASTING', discountCode: 'WINEINSPRING' },
{ id: 4, adventureName: 'RIVERSIDE CAMPING', discountCode: 'SUMMERSCAPE' },
{ id: 5, adventureName: 'TAHOE SKIING', discountCode: 'EPICPASS' },
];
// Set up state used by the React component
const [guestConnection, setGuestConnection] = useState();
// State hooks to manage the component state
const [discountCode, setDiscountCode] = useState(null);
// Asynchronously attach the extension to AEM, we must wait or the guestConnection to be set before doing anything in the modal
useEffect(() => {
(async () => {
const myGuestConnection = await attach({ id: extensionId });
setGuestConnection(myGuestConnection);
})();
}, []);
// Handle the `discountCodeList` Dropdown change
const handleDiscountCodeChange = (key) => {
if (key) {
//console.log(`DiscountCode Key: ${key}`);
//console.log(`DiscountCode Value: ${adventureDiscountCodes[key-1].discountCode}`);
//Get discount code value using selected key/index
let discountCodeValue = adventureDiscountCodes[key - 1].discountCode;
//update the `discountCode` state
setDiscountCode(discountCodeValue);
}
};
// Add the selected Adventure's Discount Code into the RTE
const addDiscountCode = () => {
if (discountCode) {
// Use `guestConnection.host.rte.applyInstructions` method and provide RTE instruction to execute.
// The instructions are passed as an array of object, that has `type` and `value` keys
guestConnection.host.rte.applyInstructions([{ type: "insertContent", value: `<strong>Discount Code: ${discountCode}</strong>` }]);
}
};
// Adobe React Spectrum (HTML code) that renders the Discount Code dropdown list, see https://react-spectrum.adobe.com/react-spectrum/index.html
return (
<Provider theme={defaultTheme}>
<Content width="100%">
<Flex width="100%">
<Form width="50%">
<Text>Selected Discount Code: <strong>{discountCode}</strong></Text>
<p />
<Divider size="M" />
<ComboBox
name="discountCodeList"
label="Type or Select an Adventure name"
defaultItems={adventureDiscountCodes}
onSelectionChange={handleDiscountCodeChange}>
{item => <Item>{item.adventureName}</Item>}
</ComboBox>
<p />
<ButtonGroup align="right">
<Button variant="accent" onPress={addDiscountCode} autoFocus>Add</Button>
<Button variant="secondary" onPress={() => setDiscountCode(null)}>Clear</Button>
</ButtonGroup>
</Form>
</Flex>
</Content>
</Provider>
);
}
export default DiscountCodes;