When I try to make a blog, I can't pass the editor in the form. I found this:
DraftJS React-Hook-Form - submitting Editor as input
but it seems that LexicalRichTextEditor does not have such a tag to pass. Can anyone help me? How can I pass properties to achieve the Add Content and Modify Content functionality?
type LexicalEditorProps = {
//config: Parameters<typeof LexicalComposer>["0"]["initialConfig"];
content: any;
};
export default function MyEditor(props: LexicalEditorProps) {
const [ editor ] = useLexicalComposerContext();
const editorStateRef = useRef();
const [saveContent, setSaveContent] = useState('');
const editorConfig: any = {
// The editor theme
theme: EditorTheme,
// Handling of errors during update
onError(error: any) {
throw error;
},
editorState: props.content,
// Any custom nodes go here
nodes: [
HeadingNode,
ListNode,
ListItemNode,
QuoteNode,
CodeNode,
CodeHighlightNode,
TableNode,
TableCellNode,
TableRowNode,
AutoLinkNode,
LinkNode
]
};
useEffect(()=>{
if(editorStateRef.current){
setSaveContent(JSON.stringify(editorStateRef.current));
}
editor.update(()=>{
const root = $getRoot();
const selection = $getSelection();
const paragraphNode = $createParagraphNode();
const textNode = $createTextNode(saveContent);
paragraphNode.append(textNode);
root.append(paragraphNode);
});
},[saveContent]);
return (
<LexicalComposer initialConfig={editorConfig}>
<div className="editor-container">
<ToolbarPlugin />
<div className="editor-inner">
<RichTextPlugin
contentEditable={<ContentEditable className="editor-input" />}
placeholder={<Placeholder />}
ErrorBoundary={LexicalErrorBoundary}
/>
<OnChangePlugin onChange={(editorState:any) => editorStateRef.current = editorState} />
<HistoryPlugin />
<AutoFocusPlugin />
<CodeHighlightPlugin />
<ListPlugin />
<LinkPlugin />
<AutoLinkPlugin />
<ListMaxIndentLevelPlugin maxDepth={7} />
<MarkdownShortcutPlugin transformers={TRANSFORMERS} />
</div>
</div>
</LexicalComposer>
);
}
export function MyForm(){
const {register, handleSubmit, control, formState: {errors}} = useForm();
const onSubmit = ( data:any) => {
console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Stack spacing={2}>
<Card>
<Controller control={control} name="content" render={()=> (
<MyEditor content={dataSet.content} />
)} />
</Card>
<Box>
<Button variant="contained" type="submit">Save</Button>
</Box>
</Stack>
</form>
);
}
I got the solution, but it's not my doing, it's the great others who helped me with the problem and hopefully will help others. https://codesandbox.io/s/purple-water-xf50bi?file=/src/App.tsx
UPDATE: Remove the if (editorRef.current ! == undefined) statement and just append field content to data
export default function App() {
const schema = yup
.object({
title: yup.string().required(),
category: yup.string().required(),
tags: yup.array().required()
})
.required();
const { register, handleSubmit } = useForm({
resolver: yupResolver(schema)
});
//Get Editor State
const editorRef: any = useRef();
const onSubmit = (data: any) => {
data.content= JSON.stringify(editorRef.current.getEditorState())
console.log(data);
};
//if (editorRef.current !== undefined) {
// if (editorRef.current !== null) {
// const latestEditorState = editorRef.current.getEditorState();
// const textContent = latestEditorState.read(() =>
// //You could change getTextContent() for your purpose
// $getRoot().getTextContent()
// );
// console.log(textContent);
// }
//}
return (
<div className="App">
<form onSubmit={handleSubmit(onSubmit)}>
<Stack spacing={2}>
<input {...register("title")} type="text" placeholder="Title" />
<input {...register("category")} type="text" placeholder="Category" />
<input type="" placeholder="Tags" />
<select {...register("tags")} id="tags" multiple>
<option value="nginx">nginx</option>
<option value="java">java</option>
<option value="react">react</option>
<option value="mui">mui</option>
</select>
<Card elevation={3}>
<MyEditor ref={editorRef} />
</Card>
<button type="submit">Save</button>
</Stack>
</form>
</div>
);
}
MyEditor.tsx
function Placeholder() {
return <div className="editor-placeholder">Enter some rich text...</div>;
}
const editorConfig: any = {
// The editor theme
theme: EditorTheme,
// Handling of errors during update
onError(error: any) {
throw error;
},
// Any custom nodes go here
nodes: [
HeadingNode,
ListNode,
ListItemNode,
QuoteNode,
CodeNode,
CodeHighlightNode,
TableNode,
TableCellNode,
TableRowNode,
AutoLinkNode,
LinkNode
]
};
// ADDED THIS:
const EditorCapturePlugin = React.forwardRef((props: any, ref: any) => {
const [editor] = useLexicalComposerContext();
useEffect(() => {
ref.current = editor;
return () => {
ref.current = null;
};
}, [editor, ref]);
return null;
});
export const MyEditor = React.forwardRef((props: any, ref: any) => {
return (
<LexicalComposer initialConfig={editorConfig}>
<div className="editor-container">
<ToolbarPlugin />
<div className="editor-inner">
<RichTextPlugin
contentEditable={<ContentEditable className="editor-input" />}
placeholder={<Placeholder />}
ErrorBoundary={LexicalErrorBoundary}
/>
{/* ADDED THIS: */}
<EditorCapturePlugin ref={ref} />
<HistoryPlugin />
<AutoFocusPlugin />
<CodeHighlightPlugin />
<ListPlugin />
<LinkPlugin />
<AutoLinkPlugin />
<ListMaxIndentLevelPlugin maxDepth={7} />
<MarkdownShortcutPlugin transformers={TRANSFORMERS} />
</div>
</div>
</LexicalComposer>
);
});