Crear un generador de páginas de arrastrar y soltar en Angular es más fácil de lo que podrías pensar gracias a GrapesJS. GrapesJS es un framework de creación web de código abierto que te permite crear páginas HTML con un editor visual de arrastrar y soltar. En este tutorial, integraremos GrapesJS en una aplicación Angular para crear un constructor de páginas con código mínimo. Aprenderás a configurar GrapesJS en Angular, usar el plugin oficial GrapesJS Basic Blocks para bloques de contenido listos, exportar el HTML/CSS diseñado e incluso guardarlo en un backend. Usaremos Angular v20 (la última versión estable a octubre de 2025) y la última librería GrapesJS para asegurarnos de que estés al día.
Al final de esta guía paso a paso, tendrás un constructor de páginas funcional en Angular donde los usuarios podrán arrastrar bloques básicos (texto, imágenes, columnas, etc.) a un lienzo, estilizarlos usando los editores integrados de GrapesJS y guardar los resultados. ¡Vamos a empezar!
Requisitos previos
Asegúrate de tener instalado y configurado lo siguiente antes de continuar:
- Node.js y npm – Instala la última versión LTS de Node.js que viene con npm.
- Angular CLI – Instala globalmente con instalación npm -g @angular/cli. Este tutorial utiliza Angular CLI 20.
- Conocimientos básicos de Angular – Comprensión de componentes, módulos y servicios en Angular.
- Un editor de código – por ejemplo, VS Code, WebStorm, etc., para editar los archivos de tu proyecto.
- Conexión a Internet – GrapesJS se instalará vía npm.
Paso 1: Montaje del proyecto Angular
Primero, crea un nuevo proyecto Angular usando la CLI de Angular. Llamaremos al proyecto grapesjs-pagebuilder (puedes elegir cualquier nombre):
ng new grapesjs-pagebuilder
Sigue las indicaciones de la CLI (puedes saltarte añadir enrutamiento para esta demo sencilla y usar CSS como formato de hoja de estilo). Una vez generado el proyecto, navega al directorio del proyecto y comienza el servidor de desarrollo:
cd grapesjs-pagebuilder ng serve -o
Esto abrirá la página de bienvenida predeterminada de Angular en http://localhost:4200/. A continuación, configuraremos la estructura de nuestro creador de páginas. Genera un nuevo componente Angular que aloje el editor GrapesJS. La llamaremos PageBuilderComponent:
ng generador de páginas de componentes
Esto creará page-builder.component.ts, sus archivos HTML/CSS y actualizará el módulo de la aplicación. Para este tutorial, queremos que nuestro componente creador de páginas ocupe toda la aplicación. Abre src/app/app.component.html y sustituye su contenido por el selector de <constructor de páginas></constructor de páginas> (y elimina el texto de plantilla por defecto). Esto garantiza que nuestro componente de construcción de páginas se renderice como la página principal.
Ahora tenemos una app Angular nueva lista para la integración de GrapesJS.
Paso 2: Instalación de GrapesJS y el plugin Basic Blocks
Con nuestro proyecto Angular listo, instalemos GrapesJS y el plugin oficial Basic Blocks . El plugin Basic Blocks ofrece un conjunto de bloques de contenido preconstruidos (texto, imágenes, columnas, etc.) que podemos arrastrar y soltar. Abre un terminal en el directorio de tu proyecto y ejecuta:
npm install grapesjs grapesjs-blocks-basic --save
Esto añadirá GrapesJS y el plugin de bloques básicos a tus dependencias de proyecto. Una vez instalado, debemos asegurarnos de que Angular conozca los recursos GrapesJS (archivos CSS/JS) y maneje las definiciones de TypeScript.
Incluye activos de GrapesJS en angular.json
GrapesJS viene con su propio CSS y también tenemos un plugin JS para incluir. Abre angular.json y localiza las opciones de compilación para tu app (en opciones de proyectos -> YOUR_APP_NAME -arquitecto > -> de compilar ->). Añadir los archivos GrapesJS a los arrays de estilos y scripts, por ejemplo:
"estilos": [ "node_modules/grapesjs/dist/css/grapes.min.css", "src/styles.css" ], "scripts": [ "node_modules/grapesjs/dist/grapes.min.js", "node_modules/grapesjs-blocks-basic/dist/index.js" ]
Esto asegurará que el CSS central de GrapesJS y los scripts (incluido el script básico del plugin de bloques) se carguen cuando la aplicación se ejecute. El CSS estilizará el editor GrapesJS (lienzo, paneles, etc.), y los scripts JS harán que grapesjs y el plugin estén disponibles globalmente.
Establecer definiciones de TypeScript
Si intentas importar GrapesJS en un archivo Angular TypeScript, podrías encontrarte con errores porque GrapesJS no viene con definiciones de tipos TypeScript. Para evitar errores de compilación de TypeScript (por ejemplo, "No se pudo encontrar un archivo de declaración para el módulo 'grapesjs'"), crea un archivo de definición. En la carpeta project src/, añade un nuevo archivo llamado grapesjs.d.ts con el siguiente contenido:
declarar el módulo 'grapesjs'; declarar el módulo 'grapesjs-blocks-basic';
Esto declara los módulos para que TypeScript los trate como cualquiera y no se queje cuando los importemos. Ahora estamos listos para usar GrapesJS en nuestro código de Angular.
(Si usas TypeScript y prefieres una tipificación más fuerte, GrapesJS ofrece un helper usePlugin para plugins que mejoren la seguridad de tipos. Para simplificar, seguiremos con la configuración básica.)
Paso 3: Integración de GrapesJS en un componente angular
Ahora viene la parte principal: incrustar el editor GrapesJS en nuestro componente Angular. Inicializaremos el editor GrapesJS en el PageBuilderComponent que hemos creado.
3.1 Configuración de plantillas de componentes
Abre page-builder.component.html. Necesitamos un elemento contenedor para que el editor GrapesJS lo monte. Añade un div que actúe como contenedor de lienzo del editor. También incluimos un encabezado sencillo como contenido inicial (GrapesJS puede importar el HTML existente dentro del contenedor). Además, añadiremos un botón de Guardar que activará la exportación del contenido:
<button (click)="savePage()">Guardar página</button> <div #gjsContainer> <h2>Mi primera página GrapesJS</h2> </div>
Aquí:
- El #gjsContainer es una referencia de plantilla que usaremos para obtener el elemento DOM en nuestra clase de componentes.
- La <h2>Mi primera página GrapesJS</h2> dentro del contenedor es contenido de ejemplo que GrapesJS cargará inicialmente (puedes poner cualquier contenido provisional aquí).
3.2 Clase de componente: Inicialización de GrapesJS
Abre page-builder.component.ts. Importaremos GrapesJS y el plugin, y luego inicializaremos el editor en los hooks del ciclo de vida del componente.
Primero, importa los módulos necesarios y declara una propiedad para la instancia del editor:
import { AfterViewInit, Component, ElementRef, OnDestroy, ViewChild } de '@angular/core';
importar uvas de 'uvas';
importar basicBlocks de 'grapesjs-blocks-basic'; Plugin
Basic Blocks ... (otras importaciones como el servicio y lo de Angular)
@Component({
selector: 'app-page-builder',
templateUrl: './page-builder.component.html',
styleUrls: ['./page-builder.component.css']
})
export class PageBuilderComponent implementa AfterViewInit, OnDestroy {
@ViewChild('gjsContainer', { static: false }) editorContainer!: ElementRef<HTMLDivElement>;
EDITOR: Cualquiera; almacenaremos aquí la instancia
del editor GrapesJS constructor(private pageService: PageService) { }
Explicación:
- Usamos @ViewChild('gjsContainer') para capturar la referencia a la #gjsContainer> < div en nuestra plantilla
- . Esto nos da acceso al elemento DOM real donde queremos que GrapesJS renderice.
- Implementamos AfterViewInit para inicializar GrapesJS una vez que la vista está lista (para que editorContainer esté lleno) y OnDestroy para limpiar el editor cuando el componente se destruye.
- Importamos grapesjs y el plugin (grapesjs-blocks-basic) en la parte superior. La importación del plugin nos da una función que podemos pasar a GrapesJS.
Ahora, dentro de la clase:
ngAfterViewInit(): void {
Inicialize GrapesJS editor
this.editor = grapesjs.init({
Bind editor al contenedor del div element
: this.editorContainer.nativeElement, usando el elemento ViewChild:contentReference[oaicite:9]{index=9}:contentReference[oaicite:10]{index=10}
fromElement: true, importa contenido inicial del contenedor INNERHTML:contentReference[oaicite:11]{index=11}
height: '700px',
width: 'auto',
Desactiva el almacenamiento local por ahora (sin autoguardado)
storageManager: false,
Incluye los plugins
de plugins Basic Blocks: [basicBlocks], pluginsOpts: {
[basicBlocks]: {
Aquí puedes personalizar las opciones de plugins (por ejemplo, qué bloques incluir)
}
}
});
El editor GrapesJS ahora está montado y es visible.
}
Desglosemos las opciones de configuración importantes que pasamos a grapesjs.init():
- contenedor – El elemento o selector para montar el editor. Aquí pasamos el elemento DOM nativo de nuestro ViewChild (this.editorContainer.nativeElement)
- . Esto adjunta GrapesJS a la #gjsContainer> < div de nuestra plantilla.
- fromElement – Indica a GrapesJS que cargue el contenido del editor desde el HTML dentro del elemento contenedor
- . Como ponemos una <h2>Mi primera página GrapesJS</h2> en la div, el editor empezará con eso como componente en el lienzo.
- altura / ancho – Establece las dimensiones del editor. Usamos 700px de altura (puedes ajustarlo o usar '100vh') y ancho 'automático' para llenar el ancho del contenedor.
- storageManager – GrapesJS tiene un gestor de almacenamiento (por ejemplo, para guardar en localStorage). Lo hemos puesto en falso para desactivar el guardado automático por ahora
- . Esto impide que GrapesJS intente guardar el estado automáticamente (nosotros gestionaremos el guardado manualmente).
- plugins – Una variedad de plugins para usar. Aquí incluimos nuestro plugin basicBlocks importado
- . Este plugin añade un conjunto de bloques básicos de contenido (texto, enlace, imagen, vídeo, columnas, etc.) al GrapesJS Block Manager.
- pluginsOpts – Opciones para los plugins. Proporcionamos un objeto de opciones vacío para basicBlocks (usando la función de plugin como clave). Por defecto, el plugin de bloques básicos añadirá todos sus bloques (columnas, texto, imagen, etc.) con los ajustes por defecto
- . (Puedes personalizarlo— por ejemplo, para excluir un bloque como Map, podrías especificar bloques: ['column1','column2',...,''video'] omitiendo 'mapa' en las opciones
- . En nuestro caso, usaremos todos los bloques por defecto.)
A continuación se muestra una tabla resumen de las opciones clave de configuración de GrapesJS que hemos utilizado y qué hacen:

Después de llamar a grapesjs.init(...), aparecerá la interfaz del editor GrapesJS dentro de nuestro componente. Por defecto, GrapesJS carga con un conjunto de paneles y botones. Por ejemplo, verás una barra superior con opciones (como desactivar el panel de bloques, deshacer/rehacer, etc.), un lienzo en el centro (donde aparece el <h2>) y a la derecha un panel de estilo/ajustes. En el lado izquierdo, habrá un panel de bloques que contiene los bloques Basic proporcionados por el plugin (texto, enlace, imagen, vídeo, etc.). Puedes arrastrar estos bloques al lienzo para construir tu página.
Propina: Por defecto, el panel de bloques en GrapesJS está oculto hasta que haces clic en el botón "Bloques" (en la barra de herramientas superior izquierda). Haz clic en el icono de Bloques para activar el panel de bloques y ver los bloques disponibles para arrastrar y soltar. La interfaz predeterminada de GrapesJS incluye este botón de alternar. Si es necesario, puedes configurar GrapesJS para mostrar el panel de bloques por defecto (por ejemplo, usando un panel personalizado o la opción appendTo en la configuración de blockManager), pero por ahora usar el comportamiento por defecto está bien.
3.3 Limpieza: Destruir el editor en la destrucción de componentes
Para evitar fugas de memoria o problemas si nuestro componente se descarga, es buena práctica destruir la instancia del editor GrapesJS cuando el componente se destruye. Implementamos ngOnDestroy para nuestro componente:
ngOnDestroy(): void {
if (this.editor) {
this.editor.destroy();
}
}
}
Esto llama al método destroy() del editor para descargar correctamente los oyentes de eventos y recursos gratuitos. GrapesJS proporciona editor.destroy() para este propósito (activa eventos de destrucción interna para limpiar). Ahora nuestra instancia GrapesJS terminará limpiamente si el usuario se aleja del componente.
En este punto, tenemos GrapesJS completamente integrado en Angular. Puedes ejecutar ng serve y navegar a la app para verificar: deberías ver la interfaz del editor de GrapesJS, con el encabezado de tu muestra en el lienzo y una barra de herramientas. Prueba a arrastrar un bloque (por ejemplo, un bloque de texto o imagen) desde el panel de Bloques al lienzo para asegurarte de que todo funciona.
Paso 4: Exportar el HTML y CSS de GrapesJS
Una de las características más potentes de GrapesJS es que permite exportar la página creada por el usuario como HTML y CSS limpios. Hemos añadido un botón de "Guardar página" en nuestra plantilla; ahora implementaremos la lógica para extraer el HTML/CSS de GrapesJS cuando se haga clic en este botón.
En nuestra clase PageBuilderComponent, ya tenemos un método savePage() conectado al botón. Vamos a implementarlo:
savePage(): void {
Obtener el HTML y CSS de GrapesJS editor
const html = this.editor.getHtml();
const css = this.editor.getCss();
console.log('HTML exportado:', html);
console.log('CSS exportado:', css);
Opcionalmente, envía el contenido al backend
this.pageService.savePage(html, css).subscribe({
next: response => console.log('¡Página guardada con éxito!', respuesta),
error: err => console.error('Error guardando página:', err)
});
}
Aquí usamos los métodos API getHtml() y getCss () del editor GrapesJS para recuperar los estilos actuales de marcado HTML y CSS del lienzo. GrapesJS devolverá la cadena HTML de lo que hay dentro del lienzo (la página diseñada) y la cadena CSS de todos los estilos aplicados (incluyendo clases, etc.). Por ahora los registramos en la consola y luego llamamos a un servicio para que realmente los guarde.
En esta fase, si haces clic en el botón "Guardar página" en la app en ejecución, deberías ver el HTML y CSS generados impresos en la consola del navegador. Por ejemplo, el HTML podría mostrar una estructura <div> con tus bloques y contenido, y CSS podría incluir clases que GrapesJS creó para estilizado.
Paso 5: Publicar el contenido de la página en un backend (servicio Angular)
En una aplicación real, probablemente querrás guardar el diseño de la página del usuario en un servidor backend (por ejemplo, para almacenarlo en una base de datos o sistema de archivos). Simularemos eso creando un servicio Angular para enviar el HTML/CSS a un endpoint de API backend.
5.1 Creación del Servicio
Genera un nuevo servicio (si no lo has hecho ya) llamado PageService:
Página de servicio ng generate
Esto crea page.service.ts. En este servicio, utilizaremos el HttpClient de Angular para publicar el contenido de la página en una API. Asegúrate de importar HttpClientModule en tu AppModule (en app.module.ts) para que HttpClient esté disponible.
Ahora, abre page.service.ts e implementa un método para guardar la página:
importar { Injectable } de '@angular/core';
importar { HttpClient } de '@angular/common/http';
importar { Observable } de 'rxjs';
@Injectable({
providedIn: 'root'
})
export class PageService {
private apiUrl = '/api/pages'; URL al endpoint backend (cambiar según sea necesario)
constructor(private http: HttpClient) { }
savePage(html: string, css: string): Observable<any> {
const payload = { html, css };
POST el HTML/CSS en el backend (reemplazar por tu endpoint API real)
devuelve this.http.post(this.apiUrl, payload);
}
}
En este código:
- Definimos una apiUrl (por ejemplo, '/api/pages') que debe apuntar a tu endpoint backend que se encargará de guardar los datos de la página. En una app real, sustituye esto por una URL real (por ejemplo, una ruta API en tu servidor). Para demostración, usamos un camino relativo.
- El método savePage acepta las cadenas HTML y CSS, las empaqueta en una carga útil JSON y utiliza HttpClient.post para enviar los datos al servidor.
- Devolvemos un Observable para que el llamante pueda suscribirse y gestionar la respuesta o los errores.
Asegúrate de que este servicio se preste en root (que es a través de la propiedad @Injectable providedIn). Hemos insertado este servicio en nuestro PageBuilderComponent anteriormente a través del constructor.
5.2 Uso del servicio en el componente
Ya hemos inyectado PageService en el componente y hemos llamado this.pageService.savePage(html, css).subscribe(...) en el método savePage(). Esto enviará la solicitud cuando se pulse el botón. En una implementación real, podrías mostrar un mensaje de éxito o navegar, etc., tras una partida guardada exitosa. Para nuestros propósitos, simplemente registramos el resultado.
Ahora, cuando ejecutas la aplicación y haces clic en "Guardar página", la app enviará una solicitud POST al endpoint especificado con el contenido de la página. Puedes verificar esto en la pestaña de red de herramientas de desarrollo de tu navegador. (Si no tienes realmente un backend ejecutándose en esa URL, recibirás un error, lo cual es lo esperado. En la práctica, implementarías el backend para gestionar la petición. Por ahora, nuestro enfoque está en la integración front-end.)
Conclusión
¡Enhorabuena! Has creado un generador básico de páginas de arrastrar y soltar en Angular usando GrapesJS. 🎉
En esta guía, nosotros:
- Configura un proyecto y un componente en Angular para el creador de páginas (usando Angular v20).
- Instalé GrapesJS y el plugin oficial grapesjs-blocks-basic para bloques listos para usar.
- Integré GrapesJS en un componente Angular con una gestión adecuada del ciclo de vida (inicializando en ngAfterViewInit y destruyendo en ngOnDestroy).
- Configuré GrapesJS con opciones esenciales y cargué el plugin Basic Blocks para proporcionar bloques de contenido arrastrables.
- Exporté el HTML y CSS de la página usando las APIs de GrapesJS e implementé un servicio Angular para enviar estos datos a un backend.
Usar GrapesJS dentro de Angular te ofrece una forma poderosa de ofrecer a los usuarios finales una experiencia visual de construcción de páginas mientras aprovechas el ecosistema de Angular. Puedes ampliar esta base añadiendo más plugins de GrapesJS (por ejemplo, editores de texto enriquecido, bloques personalizados, etc.), gestionando la autenticación de usuarios para guardar páginas e incluso construyendo una biblioteca de bloques personalizados específicos para tu aplicación. GrapesJS es muy extensible: podrías crear plugins de bloques personalizados o integrar el gestor de estilos para permitir que los usuarios modifiquen estilos con mayor libertad.
Próximos pasos: Quizá quieras explorar otras funciones de GrapesJS como el Style Manager y el Trait Manager, que estaban activadas automáticamente en nuestra configuración (la barra lateral derecha del editor te permite cambiar los estilos de los elementos seleccionados, etc.). También puedes configurar el Gestor de Almacenamiento para que persista los datos (por ejemplo, a localStorage o directamente a tu backend a través de la opción de almacenamiento remoto de GrapesJS) en lugar de usar un botón de guardado manual. Para una configuración más avanzada, considera usar presets de GrapesJS (como grapesjs-preset-webpage) que incluyen una colección de plugins para un editor de páginas completo, aunque en este tutorial nos ceñimos a lo básico para mostrar cómo funcionan las cosas por dentro.
Esperamos que este tutorial haya sido útil. ¡Feliz programación y disfruta creando increíbles constructores de páginas con Angular y GrapesJS! 🚀
