Issue #1436💬 RespondidoAbierto el 18 de septiembre de 2018por peakramsReacciones 3

Bloques atómicos o componentes complejos

Respuesta rápidapor artf1

El principal problema que veo es que el código fuente debería ser importable tal y como lo genera el editor, y no estoy seguro de si el editor puede distinguir el elemento separador de cualquier componente td de un componente de tabla usado para datos tabulares ni si puede captar todos los estilos para repoblar los ra...

Lee la respuesta completa abajo ↓

Pregunta

Hola,

Estoy estudiando el editor y creo que entiendo la diferencia entre componentes y bloques. Ahora, me preguntaba si GrapesJS ofrece la posibilidad de gestionar un bloque como una entidad atómica o si permite definir componentes como un árbol con nodos.

Por ejemplo, tengo un bloque llamado 'separator' que básicamente es una 'tabla' con un 'tbody', un 'tr' y un 'td' que son todos componentes en GJS. Me gustaría que al hacer clic en cualquier componente de este bloque separador, en realidad se seleccione el componente 'table' en el que configuro rasgos y propiedades personalizados que luego pueda separar programáticamente en el componente correcto del bloque (por ejemplo, establecer la altura en la tabla en realidad fijaría la altura del 'td' anidado).

Mi objetivo es dar a los usuarios la sensación de que están tratando con un solo elemento atómico, incluso si a nivel de código fuente las propiedades que establecen para ese elemento están distribuidas entre los diferentes nodos que lo componen.

El principal problema que veo es que el código fuente debería ser importable tal y como lo genera el editor, y no estoy seguro de si el editor puede distinguir el elemento separador de cualquier componente 'td' de un componente 'table' usado para datos tabulares y si puede captar todos los estilos para repoblar los rasgos y propiedades en el editor.

¿Es posible algo así?

Gracias.

Respuestas (3)

artf20 de septiembre de 2018

El principal problema que veo es que el código fuente debería ser importable tal y como lo genera el editor, y no estoy seguro de si el editor puede distinguir el elemento separador de cualquier componente td de un componente de tabla usado para datos tabulares ni si puede captar todos los estilos para repoblar los rasgos y propiedades en el editor.

Sí, es una buena pregunta, básicamente, el editor tiene una pila de tipos de componentes y cada vez que añades uno nuevo, se coloca encima de la pila

[
UnoÚltimoAñadidoComponente,
...
tabla,
imagen,
texto,
por defecto,
]

Supongamos que necesitas añadir un componente de tabla dentro del seleccionado (API del componente)

'''js const selected = editor.getSelected(); seleccionado es el modelo del componente selected.append('<table>...</table>`);

Ahora, cuando pasas el HTML, la cadena se analiza y cada [Nodo](https://developer.mozilla.org/en-US/docs/Web/API/Node) se traduce en un objeto componente (por ahora, solo un objeto JS) y una vez añadido a los componentes internos de 'selected' ('selected.components().add({ ... objeto componente... })') se convierte en el [Componente](https://grapesjs.com/docs/api/component.html). Pero para distinguir exactamente qué tipo de modelo es el Nodo, iteras sobre la pila, ejecutas cada método estático tipo ['isComponent'](https://grapesjs.com/docs/modules/Components.html#how-components-work) y compruebas si es válido (generalmente devuelves un objeto como '{ type: 'my-type', ... }`)
Así que el método 'isComponent' aquí es la clave, ahí puedes implementar la lógica correcta para que el editor entienda si es una tabla normal o la 'separadora' (el método toma el Nodo como argumento, así que simplemente usas la API de DOM normal para la lógica). 
También puedes saltarte la parte del reconocimiento configurando el tipo explícitamente, de esta manera:
'''html
<table data-gjs-type="separator">...</table>

Asegúrate de consultar también la guía sobre cómo almacenar y cargar plantillas, porque si usas el mismo HTML almacenado desde el editor para la edición, está MAL, tienes que usar los datos JSON (que ya contienen toda la información sobre tus tipos, así que simplemente te saltas el análisis y el reconocimiento).

artf20 de septiembre de 2018

el hecho de que haya devuelto un tipo para este nodo impide al editor probar los nodos internos de ese nodo en busca de un tipo de componente?

No, los nodos internos seguirán siendo recorridos, pero en realidad puedes evitarlo con esto como retorno a tu 'isComponent' '''js isComponent(el) { ... return { Tipo: 'Separador', Si el objeto devuelto contiene 'componentes', Los nodos internos se omitirán Componentes: [], } }

Pero, con esta configuración actual dices que no tienes componentes, así que en realidad lo renderizarías en tu lienzo:
'''js
<mesa ...></table>

Mesa vacía, ¿qué puedes hacer?!? Con esto: '''js componentes: [el.innerHTML],

Es lo mismo que no poner 'componentes', porque la cadena se analiza y procesa de nuevo. Lo que realmente puedes hacer, lo que creo que podría ser tu caso:
'''js
return {
			Tipo: 'Separador',
			contenido: el.innerHTML,
			Componentes: [],
		}

'content' es para cosas estáticas, el editor no creará Componentes y ni siquiera podrás seleccionarlos (al no ser un Componente, no tienes el modelo).

artf20 de septiembre de 2018

sí, la propiedad Content podría resolver mi problema, pero supongo que tengo que mantener manualmente su valor sincronizado (con manipulación de cadenas) con los cambios que hacen los usuarios en las propiedades y rasgos del componente separador, y, dado que forma parte del modelo de un componente separador, cualquier cambio en ella desencadenará una actualización de vista, ¿Derecha?

Bueno, como dijiste, 'me gustaría que el clic en cualquier componente de este bloque separador en realidad seleccione la tabla', supongo que el 'separador' era algo estático, sin necesidad de cambiar cosas internas, depende de lo que estén haciendo tus rasgos, por ejemplo. Si solo cambias los atributos del propio componente, sigue sincronizado con su vista

Si no, si dejo que los nodos internos se recorran pero compruebe los antepasados y/o los descendientes para establecer si, por ejemplo, forman parte de mi componente separador y hago que no se puedan soltar, arrastrar y no seleccionarse (quizá definiendo componentes separados como separator-tr, separator-td, etc.)? ¿Podría ser esta una mejor solución?

Sí, claro

Preguntas y respuestas relacionadas

Continúa investigando con debates sobre temas similares.

Plugins de pago que cumplen con este problema

Seleccionado por temas clave y relevancia de etiquetas para ayudarte a enviar más rápido.

Ver todos los plugins

Cargando recomendaciones de plugins de pago...

Opción gratuita

Consulta los plugins de código abierto de GrapesJS en GitHub O haz una búsqueda rápida en nuestro catálogo gratuito.

Explora plugins gratuitos →
Opción premium

Los plugins premium incluyen soporte, actualizaciones regulares y funciones listas para producción — ahorrando días de trabajo de integración.

Explora plugins premium →

Tutoriales relacionados

Guías detalladas sobre el mismo tema.

Todos los tutoriales →

Explorar categorías de plugins

Ve directamente a las páginas de categorías de plugins en el marketplace.