Pregunta: ¿Arrastrar bloques a un bloque de texto?
¿Has comprobado API-Rich-Text-Editor? Puedes añadir una acción personalizada como esta '''js editor. RichTextEditor.add('custom-vars', { icono: '<select class="gjs-field"> <valor de opción="">- Seleccionar -</option> <valor de opción="[[nombre]]">Nombre</option> <valor de opción="[[apellido]]">Apellido</option> <valor...
Lee la respuesta completa abajo ↓Pregunta
Esto no es un bug, sino una cuestión de implementación. Si este no es el lugar adecuado para hacer estas preguntas, por favor, házmelo saber.
Estamos trabajando en una implementación en la que queremos usar GrapesJS para permitir a los usuarios crear una plantilla de correo electrónico. Como parte de esta implementación estamos trabajando para crear funcionalidad de fusión de correo: hemos introducido el concepto de 'merge-fields' o 'placeholders' que reemplazaremos por los valores adecuados en el lado del servidor. Esto significa que enviamos la estructura JSON 'components' y la convertimos en HTML en el lado del servidor, reemplazando los valores a medida que avanzamos.
Por ejemplo, uno de nuestros usuarios podría introducir el text: 'Hello <username><>' y reemplazaremos ese campo de fusión '<<username>>' por el campo adecuado.
Pero aún no hemos podido implementar esto de esta manera porque no podemos arrastrar estos bloques a un bloque de texto. Solo podemos arrastrarlo a su alrededor. Así que, por ahora, estamos ampliando el RTE con un 'bloque en línea' de campo de fusión ( '<tipo de entrada=clase solo lectura de texto=mergeField data-isMergefield=1 />') y creando un bloque de campo de fusión con el mismo HTML en el gestor de bloques. Implementar un tipo DomComponent para reconocerlo ofrece un método para configurarlo. Pero parece subóptimo, nos gustaría poder arrastrar ese bloque de mergefield al lugar correcto del campo de texto.
Para permitir esto, imagino que GrapesJS tendría que poder coger el textNode y dividirlo en (al menos) dos textnodes y una etiqueta para el campo de fusión, pero no sé por dónde empezar con esto. ¿Podrías aconsejarme cómo podríamos implementar esto?
Respuestas (3)
¿Has comprobado API-Rich-Text-Editor? Puedes añadir una acción personalizada como esta '''js editor. RichTextEditor.add('custom-vars', { icono: '<select class="gjs-field"> <valor de opción="">- Seleccionar -</option> <valor de opción="[[nombre]]">Nombre</option> <valor de opción="[[apellido]]">Apellido</option> <valor de opción="[[age]]">Age</option> ',</select> Vincula el 'resultado' al oyente de 'cambio' evento: 'cambio', resultado: (rte, acción) => rte.insertHTML(acción.btn.firstChild.value), Restablece la selección al cambiar actualización: (rte, acción) => { action.btn.firstChild.value = "";} })
! [rte-acción](https://user-images.githubusercontent.com/11614725/32463242-810de0fc-c33c-11e7-81df-3524c0ad55ac.gif)
Probablemente en la próxima versión esta función estará disponible. ! disponible por mensaje
Así que 'textible' será solo otra propiedad, esto permitirá que cualquier componente se elimine dentro de los componentes de texto. Aquí está el código del componente del ejemplo anterior: '''js Define un componente con la propiedad 'textible' editor. DomComponents.addType('var-placeholder', { modelo: { Predeterminados: { Textible: 1, marcador de posición: 'VARIABLE-1', }, toHTML() { return '{{ ${this.get('placeholder')} }}'; }, }, La vista de abajo es solo un ejemplo de cómo crear una experiencia de usuario diferente Vista: { etiquetaNombre: 'span', eventos: { 'cambio': 'actualizaciónPlh', }, Actualiza el modelo una vez que se cambie la selección updatePlh(ev) { this.model.set({ placeholder: ev.target.value }); this.updateProps(); }, Cuando difuminamos desde un TextComponent, todos sus componentes hijos son aplanado mediante innerHTML y analizado por el editor. Así que mantener el estado de nuestros props sincronizados con el modelo, así que necesitamos exponer los props en el HTML updateProps() { const { el, model } = this; el.setAttribute('data-gjs-placeholder', model.get('placeholder')); }, onRender() { const { model, el } = this; const currentPlh = model.get('placeholder'); const select = document.createElement('select'); const options = [ 'VARIABLE-1', 'VARIABLE-2', 'VARIABLE-3' ]; select.innerHTML = options.map(element => '<valor de opción="${item}" ${elemento === currentPlh ? 'seleccionado' : ''}> ${item} ')</option>.unir(''); mientras que (el.primerNiño) el.removeChild(el.primerNiño); el.appendChild(select); select.setAttribute('style', 'addding: 5px; border-radius: 3px; border: none; -webkit-appearance: none;'); this.updateProps(); }, } });
Usar el componente en bloques editor. BlockManager.add('simple-block', { etiqueta: 'Bloque textible', Contenido: { Tipo: 'var-placeholder' }, });
Sí, lo he usado y prácticamente lo he conseguido funcionar. La diferencia es que yo no estoy usando un marcador de texto como tú. De hecho, estoy insertando un bloque (con un 'tipo' correspondiente) para poder configurar aún más estos marcadores de posición (por ejemplo, un campo podría ser un campo de Fecha y Hora y mi usuario podría querer configurar el formato exacto de salida para esa fecha-hora). Usé HTML5 arrastrando y soltando para implementar esto y funciona bastante bien, pero qué...
Parece que se aleja de la interfaz de usuario esperada. Creo que debería poder arrastrar un campo de fusión desde los 'bloques' y colocarlo en la posición correcta. He estado probando con el Clasificador para que esto lo permita y estoy dispuesto a esto:
! imagen
Ahora tengo el problema de que el Clasificador quiere mucho bloques reales para alinearse, así que tengo que ajustar más. Por ahora, implementar esto ha requerido cambiar en la ComponentTextView (principalmente: no vaciar la barra de herramientas para 'mergefields') y en el Sorter (si estoy pasando el cursor por un mergefield sobre un bloque de texto, insertar HTML en el activeRTE en lugar de añadir un bloque).
Actualmente estoy trabajando para que el arrastre funcione de forma más fiable (por alguna razón, cada vez que arrastro derecha el campo se añade al nodo de texto en lugar de en la posición del cursor, funciona bien al arrastrar izquierda :)), haciendo que el ordenador ignore la idea de 'bloques' cuando está dentro de un campo de texto, mostrando el marcador de posición correcto en ese caso (querría ver el cursor real) y limpiando todo.
No estoy seguro de cómo abordar el tema del Clasificador en este momento, salvo especializar bloques de texto, así que si tienes alguna idea en ese ámbito me encantaría escucharla. Puedes ver parte del código improvisado que he hecho hasta ahora en https://github.com/mathieuk/grapesjs/commit/d58c5ee5306c358cd19509f6b8affe9bb60493ed .
Preguntas y respuestas relacionadas
Continúa investigando con debates sobre temas similares.
Issue #955
[Pregunta]: Encontrar el componente asociado al elemento HTML en iframe/editor visual.
¡Hola! Estoy trabajando en una implementación de GrapesJS donde puedo arrastrar y soltar un fragmento de texto de fuera de GrapesJS hacia u...
Issue #1484
[Pregunta]: Las filas siguientes del bloque de texto no dan el cursor/editor de texto enriquecido al hacer clic, sino que se seleccionan en su lugar
He notado un comportamiento extraño en mi adaptación de GrapesJS respecto al editor de texto rico y el plugin gjs-blocks-basic. Cada vez qu...
Issue #3266
[Pregunta] ¿Cómo saber de qué bloque se genera el componente seleccionado?
Me pregunto cómo hacer una búsqueda inversa, desde el componente hasta el bloque. Uso add() del Gestor de bloques para añadir un bloque com...
Issue #1617
[Pregunta] ¿Cómo puedo evitar que el evento de bloquear:arrastrar:inicio? ¿También hay algún evento para escuchar la posición objetivo inválida?
Antes que nada, agradezco mucho vuestras respuestas a mis preguntas. Gracias por todo. Pregunta 1: Tengo una situación en la que, si un blo...
Plugins de pago que cumplen con este problema
Seleccionado por temas clave y relevancia de etiquetas para ayudarte a enviar más rápido.
Cargando recomendaciones de plugins de pago...
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 →Los plugins premium incluyen soporte, actualizaciones regulares y funciones listas para producción — ahorrando días de trabajo de integración.
Explora plugins premium →Explorar categorías de plugins
Ve directamente a las páginas de categorías de plugins en el marketplace.