将徽章添加到富文本编辑器(RTE)

上次更新: 2023-10-13
  • 创建对象:
  • Beginner
    Developer

了解如何在AEM内容片段编辑器中向富文本编辑器(RTE)添加徽章。

富文本编辑器徽章 是使富文本编辑器(RTE)中的文本不可编辑的扩展。 这意味着声明为此类的徽章只能完全删除,不能部分编辑。 这些徽章还支持RTE中的特殊着色,明确向内容作者指示文本是徽章,因此不可编辑。 此外,它们提供有关徽章文本含义的视觉提示。

RTE徽章最常见的使用案例是将其与结合使用 RTE小组件. 这允许RTE构件插入到RTE中的内容不可编辑。

通常,与小组件关联的徽章用于添加具有外部系统依赖关系,但 内容作者无法修改 插入的动态内容以保持完整性。 它们只能作为整个项目删除。

徽章 都会添加到 RTE 在内容片段编辑器中使用 rte 扩展点。 使用 rte 扩展点的 getBadges() 方法添加一个或多个徽章。

此示例说明如何添加名为的小部件 大型团体预订客户服务 查找、选择并添加特定于WKND冒险的客户服务详细信息,例如 代表姓名电话号码 在RTE内容中。 使用徽章功能 电话号码 已制作 不可编辑 但WKND内容作者可以编辑代表名称。

此外, 电话号码 样式不同(蓝色),这是徽章功能的额外用例。

为了保持简单,本示例使用 AdobeReact频谱 框架,用于开发小组件或对话框UI和硬编码的WKND客户服务电话号码。 要控制内容的非编辑和不同的样式方面,请 # 字符用于 prefixsuffix 徽章定义的属性。

扩展点

此示例将扩展到扩展点 rte 在内容片段编辑器中将徽章添加到RTE。

AEM UI已扩展 扩展点
内容片段编辑器 富文本编辑器徽章富文本编辑器小组件

扩展示例

以下示例创建 大型团体预订客户服务 构件。 通过按下 { 键,打开RTE构件上下文菜单。 通过选择 大型团体预订客户服务 上下文菜单中的选项,自定义模式将打开。

从模式中添加所需的客户服务编号后,徽章会使 电话号码不可编辑 并将其样式设置为蓝色。

延期注册

ExtensionRegistration.js,映射到 index.html route,是AEM扩展的入口点,并定义:

  • 在中定义徽章的定义 getBadges() 使用配置属性 idprefixsuffixbackgroundColortextColor.
  • 在此示例中, # 字符用于定义此徽章的边界,这意味着RTE中由以下对象包围的任何字符串 # 将被视为此徽章的实例。

此外,请参阅RTE小部件的关键详细信息:

  • 中的构件定义 getWidgets() 函数为 idlabelurl 属性。
  • url 属性值,相对URL路径(/index.html#/largeBookingsCustomerService)以加载该模式窗口。

src/aem-cf-editor-1/web-src/src/components/ExtensionRegistration.js

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 Badges
          getBadges: () => [
            {
              id: "phoneNumber",                    // Provide a unique ID for the badge
              prefix: "#",                          // Provide a Badge starting character
              suffix: "#",                          // Provide a Badge ending character
              backgroundColor: "",                  // Provide HEX or text CSS color code for the background
              textColor: "#071DF8"                  // Provide HEX or text CSS color code for the text
            }
          ],

          // RTE Widgets
          getWidgets: () => [
            {
              id: "largegroup-contact-list-widget",       // Provide a unique ID for the widget
              label: "Large Group Bookings Customer Service",          // Provide a label for the widget
              url: "/index.html#/largeBookingsCustomerService",     // Provide the "relative" URL to the widget content. It will be resolved as `/index.html#/largeBookingsCustomerService`
            },
          ],
      }
    });
  };

  init().catch(console.error);

  return <Text>IFrame for integration with Host (AEM)...</Text>;
}

添加 largeBookingsCustomerService 路由 App.js

在主React组件中 App.js,添加 largeBookingsCustomerService 用于呈现上述相对URL路径的UI的路由。

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="/largeBookingsCustomerService" element={<LargeBookingsCustomerService />} />
</Routes>
...

创建 LargeBookingsCustomerService React组件

使用创建构件或对话框UI AdobeReact频谱 框架。

添加客户服务详细信息时,React组件代码将在电话号码变量周围加上 # 注册徽章字符,以将其转换为徽章,如 #${phoneNumber}#,因此使其不可编辑。

以下是的主要亮点 LargeBookingsCustomerService 代码:

  • UI使用React Spectrum组件渲染,例如 组合框按钮组按钮
  • largeGroupCustomerServiceList 数组具有代表性名称和电话号码的硬编码映射。 在现实场景中,此数据可以从AdobeAppBuilder操作或外部系统、自主开发或基于云提供商的API网关中检索。
  • guestConnection 已使用 useEffect React挂钩 并作为组件状态进行管理。 用于与AEM主机通信。
  • handleCustomerServiceChange 函数获取代表性姓名和电话号码,并更新组件状态变量。
  • addCustomerServiceDetails 函数使用 guestConnection 对象提供要执行的RTE指令。 在本例中 insertContent 指令和HTML代码段。
  • 创建 电话号码不可编辑 使用徽章, # 特殊字符添加在 phoneNumber 变量,如 ...<div><p>Phone Number: #${phoneNumber}#</strong></p></div>.

src/aem-cf-editor-1/web-src/src/components/LargeBookingsCustomerService.js

import {
  Button,
  ButtonGroup,
  Text,
  Divider,
  ComboBox,
  Content, Flex, Form,
  Item,
  Provider, defaultTheme
} from '@adobe/react-spectrum';
import { attach } from '@adobe/uix-guest';
import React, { useEffect, useState } from 'react';
import { extensionId } from './Constants';


const LargeBookingsCustomerService = () => {

  // The Large Group Bookings Customer Service
  // 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 largeGroupCustomerServiceList = [
    { id: 1, repName: 'Max', phoneNumber: '1-800-235-1000' },
    { id: 2, repName: 'John', phoneNumber: '1-700-235-2000' },
    { id: 3, repName: 'Leah', phoneNumber: '1-600-235-3000' },
    { id: 4, repName: 'Leno', phoneNumber: '1-500-235-4000' }
  ];

  // Set up state used by the React component
  const [guestConnection, setGuestConnection] = useState();

  // State hooks to manage the component state
  const [repName, setRepName] = useState(null);
  const [phoneNumber, setPhoneNumber] = 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 `customerService` Dropdown change
  const handleCustomerServiceChange = (id) => {

    if (id) {
      //Get Customer Service RepName and Phone Number values using selected id

      const rep = largeGroupCustomerServiceList.filter((r) => r.id === id)[0];

      //update the `repName` state
      setRepName(rep?.repName);

      //update the `phoneNumber` state
      setPhoneNumber(rep?.phoneNumber);
    }
  };

  // Add the selected Customer Service details into the RTE
  const addCustomerServiceDetails = () => {

    if (repName && phoneNumber) {
      // 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: `<div><p>Representative Name: <strong>${repName}</strong></p></div><div><p>Phone Number: #${phoneNumber}#</strong></p></div>` }]);
    }
  };


  // Adobe React Spectrum (HTML code) that renders the Customer Service 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>Representative Name: <strong>{repName}</strong></Text>
            <Text>Phone Number: <strong>{phoneNumber}</strong></Text>

            <p />

            <Divider size="M" />


            <ComboBox
              name="customerService"
              label="Type or Select Phone Number"
              defaultItems={largeGroupCustomerServiceList}
              onSelectionChange={handleCustomerServiceChange}>
              {item => <Item>{item.phoneNumber}</Item>}
            </ComboBox>

            <p />

            <ButtonGroup align="right">
              <Button variant="accent" onPress={addCustomerServiceDetails}>Add</Button>
              <Button variant="secondary" onPress={() => {setPhoneNumber(null); setRepName(null);}}>Clear</Button>
            </ButtonGroup>

          </Form>
        </Flex>
      </Content>
    </Provider>
  );

};

export default LargeBookingsCustomerService;

在此页面上