Reputation: 537
I want to generate HTML format from editorState in Lexical Rich Editor, I'm able to get selection with editorState and what will be best to save into database, HTML or some sort of JSON format?
and I want to show this HTML outside of editor. here is some example of code
const onChange = (editorState) => {
const editorStateTextString = editorState.read(() => {
const selection = $getSelection();
console.log(selection);
return $getRoot().getTextContent();
});
// TODO: saving text only at the moment
if (changeHandler) {
changeHandler(editorStateTextString);
}
};
<LexicalComposer initialConfig={editorConfig}>
<div className="editor-container">
<ToolbarPlugin aditionalTools={aditionalTools} />
<div className="editor-inner">
<RichTextPlugin
contentEditable={<ContentEditable className="editor-input" />}
placeholder={<Placeholder placeholder={placeholder} />}
/>
<OnChangePlugin ignoreInitialChange onChange={onChange} />
</div>
</div>
</LexicalComposer>
Upvotes: 13
Views: 7196
Reputation: 799
To build on Steve2955's answer, another possible implemention of the onChange
functionality is to use the registerTextContentListener
method of the editor instance:
useEffect(() => {
...
editor.registerTextContentListener((text) => {
editor.read(() => {
console.log(text, $generateHtmlFromNodes(editor));
});
});
}, [editor]);
Upvotes: 0
Reputation: 1037
<OnChangePlugin onChange={(editorState, editor) => {
editorState.read(() => {
const html = $generateHtmlFromNodes(editor);
console.log(html);
});
}} />
This will console html
Upvotes: 4
Reputation: 1
You can grab editor from initialConfig
using the editorState
key.
const initialConfig = {
editorState: (editor) => {
editor.update(() => {
const parser = new DOMParser();
const dom = parser.parseFromString(htmlString, ‘text/html’);
const nodes = $generateNodesFromDOM(editor, dom);
$insertNodes(nodes);
}):
}
}
Then just pass initialConfig
to LexicalComposer
.
Upvotes: 0
Reputation: 680
I have been running into the same issue and solved it by using the following simple plugin. The hard part was getting a reference to the editor, which is what I used useLexicalComposerContext()
for.
import { useState, useEffect } from "react";
import { OnChangePlugin } from "@lexical/react/LexicalOnChangePlugin";
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
import { $generateHtmlFromNodes, $generateNodesFromDOM } from "@lexical/html";
import { $insertNodes } from "lexical";
interface Props {
initialHtml?: string;
onHtmlChanged: (html: string) => void;
}
const HtmlPlugin = ({ initialHtml, onHtmlChanged }: Props) => {
const [editor] = useLexicalComposerContext();
const [isFirstRender, setIsFirstRender] = useState(true);
useEffect(() => {
if (!initialHtml || !isFirstRender) return;
setIsFirstRender(false);
editor.update(() => {
const parser = new DOMParser();
const dom = parser.parseFromString(initialHtml, "text/html");
const nodes = $generateNodesFromDOM(editor, dom);
$insertNodes(nodes);
});
}, []);
return (
<OnChangePlugin
onChange={(editorState) => {
editorState.read(() => {
onHtmlChanged($generateHtmlFromNodes(editor));
});
}}
/>
);
};
export default HtmlPlugin;
You can use it in your LexicalComposer
like so:
<LexicalComposer initialConfig={editorConfig}>
<div className="editor-container">
<ToolbarPlugin aditionalTools={aditionalTools} />
<div className="editor-inner">
<RichTextPlugin
contentEditable={<ContentEditable className="editor-input" />}
placeholder={<Placeholder placeholder={placeholder} />}
/>
{/* see here */}
<HtmlPlugin
onHtmlChanged={(html) => console.log(html)}
initialHtml="<h1>Test</h1><p>Lorem ipsum dolor sit amet</p>"
/>
</div>
</div>
</LexicalComposer>
Upvotes: 15
Reputation: 29
You should definitely save the JSON into the database. The most important thing is that this let's you decide how to render it. Maybe in some cases you want to render to HTML, but in others (eg: mobile) you want to render to native elements.
To get the JSON structure you can do:
editor.getEditorState().toJSON();
Also, regarding your second question. Here's how you can get the HTML:
import {$generateHtmlFromNodes} from '@lexical/html';
...
const htmlString = $generateHtmlFromNodes(editor, null);
NOTE: you need to call the above method inside the Lexical context (ie: inside a callback like
editor.update
Upvotes: 1