Uso de DraftJs con WYSWYG : necesito crear un botón personalizado en la barra de herramientas. Al hacer clic en el botón, se agrega algo de HTML personalizado (que incluye <button> ) al contenido mismo.
Sé cómo agregar un botón personalizado, los documentos están ahí. El botón se agrega y al hacer clic llamo al método definido insertText . Pero con insertText (un método en la clase DraftModifier de draft.js) solo parece agregar mi código HTML como una cadena. ¿Hay algún método diferente que deba usar para agregar HTML personalizado al contenido? Quiero agregar HTML real.
Aquí está la declaración de TS:
static insertText( contentState: ContentState, targetRange: SelectionState, text: string, inlineStyle?: DraftInlineStyle, entityKey?: string ): ContentState;Puede usar replaceWithFragment . Para construir el fragmento que desea insertar, primero convierta la cadena en bloques HTML con la utilidad convertFromHTML
const htmlContent = convertFromHTML(text);luego, use otra utilidad para pasar la matriz de bloques de contenido a un mapa
const htmlContentMap = BlockMapBuilder.createFromArray( htmlContent.contentBlocks ); y llame a replaceWithFragment de la misma manera que estaba llamando a insertText , pero con el mapa de contenido HTML que creó
const newContent = Modifier.replaceWithFragment( currentContent, currentSelection, htmlContentMap );ACTUALIZAR
DraftJS no admite la etiqueta de botón de forma predeterminada, pero puede agregarla como un procesamiento de bloque personalizado
primero, cree un mapa de tipos fusionando las etiquetas compatibles predeterminadas con la etiqueta del botón
import { ... DefaultDraftBlockRenderMap, ... } from "draft-js"; ... const mapWithButton = Map({ button: { element: "button" } }).merge(DefaultDraftBlockRenderMap); ... y páselo como tercer argumento a la función convertFromHTML
const htmlContent = convertFromHTML( text, undefined, mapWithButton );cree una función de representación de bloques personalizada y pásela al Editor
function myBlockRenderer(contentBlock: ContentBlock) { const type = contentBlock.getType(); if (type === "button") { return { component: () => { return ( <button onClick={() => console.log("doesn't seem to work :(")}> {contentBlock.getText()} </button> ); }, editable: false, }; } } ... <Editor ... customBlockRenderFunc={myBlockRenderer} />Funciona porque muestra el botón, aunque a veces cuando hay texto antes del punto cuando lo insertas, fusiona el texto anterior con el texto del botón sin mostrar el botón. El click tampoco funciona probablemente por esto
Si su renderizador de bloques personalizado requiere la interacción del mouse, a menudo es aconsejable configurar temporalmente su Editor en readOnly={true} durante esta interacción. De esta forma, el usuario no activa ningún cambio de selección dentro del editor mientras interactúa con el bloque personalizado.
https://codesandbox.io/s/insert-html-draftjs-73rmc?file=/src/Editor.tsx
En la documentación de react-draft-wysiwyg, hay una parte dedicada al uso de html, que se cita a continuación. Los pasos esenciales son:
ContentBlock .convertFromHtml .ContentState con ese ContentBlock .ContentEditor con ese ContentStateeditorState del Editor de react-draft-wysiwyg con ese objeto ContentEditor .Aquí hay dos ejemplos en vivo para lograr eso: 1 , 2 .
Cita de la documentación de react-draft-wysiwyg:
draftjs-to-html se puede usar para convertir
RawDraftContentStatea html.
html-to-draftjs brinda la opción de convertir HTML generado por react-draft-wysiwyg nuevamente a draftJSContentState, que se puede usar para inicializar el Editor.import React, { Component } from 'react'; import { EditorState, convertToRaw, ContentState } from 'draft-js'; import { Editor } from 'react-draft-wysiwyg'; import draftToHtml from 'draftjs-to-html'; import htmlToDraft from 'html-to-draftjs'; class EditorConvertToHTML extends Component { constructor(props) { super(props); const html = '<p>Hey this <strong>editor</strong> rocks 😀</p>'; const contentBlock = htmlToDraft(html); if (contentBlock) { const contentState = ContentState.createFromBlockArray(contentBlock.contentBlocks); const editorState = EditorState.createWithContent(contentState); this.state = { editorState, }; } } onEditorStateChange: Function = (editorState) => { this.setState({ editorState, }); }; render() { const { editorState } = this.state; return ( <div> <Editor editorState={editorState} wrapperClassName="demo-wrapper" editorClassName="demo-editor" onEditorStateChange={this.onEditorStateChange} /> <textarea disabled value={draftToHtml(convertToRaw(editorState.getCurrentContent()))} /> </div> ); } }