Widgets personalizados (React)
AWE le permite ampliar la interfaz que proporciona con sus propios componentes JavaScript — incluidas bibliotecas de terceros y sus estilos — incrustándolos en una pantalla mediante el elemento <widget>. En el cliente React, los widgets se resuelven por su type contra un registro de widgets del lado cliente, por lo que puede conectar lo que necesite a nivel de aplicación sin modificar el framework.
Esta guía recorre un ejemplo completo y funcional: un calendario de eventos (construido sobre la biblioteca de terceros FullCalendar) añadido a un proyecto AWE con React.
Cómo funciona
Cuando coloca un widget en una pantalla:
<widget type="event-calendar" id="eventCalendar" style="expand"/>
el cliente React busca el type del widget en su registro y renderiza el componente correspondiente:
- El paquete
awe-react-clientexponeregisterWidget(type, component)ygetWidget(type). El cliente resuelve cada nodo<widget>contra el registro por sutype. - Los widgets integrados (
file-manager,log-viewer,help-viewer,pdf-viewer,carousel) se registran mediante este mismo mecanismo, por lo que un widget de aplicación no es un caso especial. - Todos los atributos del nodo del widget (
id,style, ...) se pasan a su componente como props. - Si ningún componente coincide con
type, el cliente renderiza un marcador de posición (The widget <type> has not been created yet.) en lugar de fallar.
Para registrar su propio componente, importe registerWidget desde el punto de entrada principal del cliente y llámelo una vez al arrancar la aplicación.
Pasos
1. Añadir la dependencia de la biblioteca
Instale la biblioteca de componentes en su proyecto (aquí, FullCalendar y su adaptador para React):
npm install --save @fullcalendar/core @fullcalendar/daygrid @fullcalendar/timegrid @fullcalendar/list @fullcalendar/interaction @fullcalendar/react
2. Escribir el componente del widget
Cree el componente en src/js/widgets/, por ejemplo src/js/widgets/EventCalendar.jsx. Puntos clave:
- Es un componente React normal. AWE pasa los atributos del nodo del widget como props, así que extraiga
idystylede ellas. - Renderice su componente de terceros (aquí,
<FullCalendar>) dentro de su propio contenedor. - Siga el idioma de AWE mediante
react-i18next:useTranslation()le proporcionatpara las etiquetas ei18n.languagepara el código del idioma activo de AWE (p. ej.en-GB,es-ES).
import React, { useState } from "react";
import PropTypes from "prop-types";
import { useTranslation } from "react-i18next";
import FullCalendar from "@fullcalendar/react";
import dayGridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import listPlugin from "@fullcalendar/list";
import interactionPlugin from "@fullcalendar/interaction";
import esLocale from "@fullcalendar/core/locales/es";
import enGbLocale from "@fullcalendar/core/locales/en-gb";
// AWE language codes mapped to FullCalendar locales
const CALENDAR_LOCALES = {
"es-ES": esLocale,
"en-GB": enGbLocale
};
// Receives the widget node attributes (id, style, ...) as props
function EventCalendar({ id, style = "" }) {
const { t, i18n } = useTranslation();
const [events, setEvents] = useState([/* ... in-memory demo events ... */]);
return (
<div id={id} className={`awe-ec ${style}`}>
<div className="awe-ec-mount">
<FullCalendar
plugins={[dayGridPlugin, timeGridPlugin, listPlugin, interactionPlugin]}
initialView="dayGridMonth"
height="100%"
locale={CALENDAR_LOCALES[i18n.language] ?? enGbLocale}
events={events}
/>
</div>
{/* Composer to create/edit events (not a native <form> — see caution below) */}
</div>
);
}
EventCalendar.propTypes = {
id: PropTypes.string.isRequired,
style: PropTypes.string
};
export default EventCalendar;
Lea el idioma activo con react-i18next: const { t, i18n } = useTranslation(). Use i18n.language (códigos como en-GB, es-ES) para elegir el locale de la biblioteca de terceros, y t("KEY") para sus propias etiquetas, de modo que cambien con el idioma de AWE. No se base en el idioma del navegador.
<form> nativo, sin diálogos nativosLa pantalla de AWE ya envuelve su contenido en un <form>, y los formularios HTML no se pueden anidar — por lo que no añada otro <form> dentro de su widget. Gestione crear/editar/eliminar con botones y manejadores onClick. Del mismo modo, mantenga las interacciones en línea en lugar de usar alert() / confirm() / prompt(), y persista los datos mediante el server-action del widget en lugar de en memoria (los eventos en memoria de arriba son solo para la demostración).
3. Registrar el componente
Registre el widget una vez al arrancar la aplicación en src/js/main.js, usando registerWidget desde el punto de entrada principal del cliente:
const { registerWidget } = require('awe-react-client/js/main');
const { default: EventCalendar } = require('./widgets/EventCalendar');
// Custom widgets
registerWidget("event-calendar", EventCalendar);
El primer argumento ("event-calendar") es el type usado en el XML de la pantalla; el segundo es su componente.
4. Añadir los estilos
Añada los estilos de su widget en src/css/main.css (importado por src/js/main.js). FullCalendar v6 inyecta su propio CSS base en tiempo de ejecución, por lo que principalmente sobrescribe sus propiedades personalizadas de CSS (acotadas al contenedor de su widget) para integrarse con el tema activo de AWE:
.awe-ec {
display: flex;
flex-direction: column;
height: 100%;
}
.awe-ec-mount {
/* FullCalendar v6 custom properties */
--fc-border-color: #e2e8ec;
--fc-today-bg-color: rgba(86, 158, 27, 0.08);
--fc-event-bg-color: #569e1b;
--fc-event-border-color: #569e1b;
}
5. Añadir la pantalla
Cree una pantalla que incruste el widget. El type coincide con la clave que registró:
<screen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://aweframework.gitlab.io/awe/docs/schemas/screen.xsd"
template="window" label="MENU_TEST_EVENT_CALENDAR">
<tag source="center" type="div" expandible="vertical" style="expand">
<widget type="event-calendar" id="eventCalendar" style="expand"/>
</tag>
</screen>
6. Añadir la opción de menú y los locales
Registre una opción de menú que apunte a la pantalla y añada las claves de locale usadas por la pantalla y el widget:
<!-- menu/private.xml -->
<option name="event-calendar-test" label="MENU_TEST_EVENT_CALENDAR" screen="event-calendar-test" icon="calendar"/>
<!-- locale/Locale-en-GB.xml -->
<locale name="MENU_TEST_EVENT_CALENDAR" value="Event calendar"/>
<locale name="SCR_EVENT_CALENDAR_NEW" value="New event"/>
<locale name="SCR_EVENT_CALENDAR_TITLE" value="Event title"/>
Notas
typees la clave de extensión — es una cadena libre, por lo que no está limitado a un conjunto fijo de componentes. Las restricciones de pantalla/perfil siguen siendo el lugar adecuado para controlar el acceso.- Los widgets integrados y los personalizados comparten el mismo registro —
registerWidgetes exactamente cómo el cliente registrafile-manager,log-viewery el resto, por lo que no hace falta ningún cambio en el framework para añadir el suyo. - Pase configuración al componente con
<widget-parameter>; el nodo del widget (incluidos sus parámetros) llega a su componente como props. - Para el modelo de resolución compartido con el cliente Angular, consulte la referencia de la API de Widgets.