Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to render Headless CMS Richtext Custom Lexical Node #4380

Open
bschulz87 opened this issue Nov 12, 2024 · 4 comments
Open

How to render Headless CMS Richtext Custom Lexical Node #4380

bschulz87 opened this issue Nov 12, 2024 · 4 comments

Comments

@bschulz87
Copy link

bschulz87 commented Nov 12, 2024

Hello,

i've followed the documentation on how to extend the Lexical Editor and cannot figure out how make the CMS render saved custom nodes. Inserting, saving and publishing works and i also get the the Node as Lexical State from the GraphQL API. After a refresh the nodes content are fetched from graphql but are missing the Richtext Editor.

I'm aware of the lexical-converter mentioned in https://www.webiny.com/docs/core-development-concepts/extending-and-customizing/lexical-tools#custom-nodes but i cannot find an example on how to implement it for the LexicalEditorConfig.

Version of Webiny is v5.40.5

App.tsx

    return (
        <Admin>
            <Cognito />
            <Extensions />
            <LexicalEditorConfig>
                <Plugin name={"insertColumns"} element={<InsertColumnsPlugin />} />
                <ToolbarAction name={"insertColumns"} element={<InsertColumnsAction />} />
                <Node name={"layoutContainer"} node={LayoutContainerNode} />
                <Node name={"layoutItem"} node={LayoutItemNode} />
            </LexicalEditorConfig>
        </Admin>
    );
};

Content from the /manage CmsEntriesGetPage request the CMS does on page detail:

	"children": [
		{
			"children": [
				{
					"detail": 0,
					"format": 0,
					"mode": "normal",
					"style": "",
					"text": "Paragraph",
					"type": "text",
					"version": 1
				}
			],
			"direction": "ltr",
			"format": "",
			"indent": 0,
			"type": "paragraph-element",
			"version": 1,
			"textFormat": 0,
			"styles": [
				{
					"styleId": "paragraph1",
					"type": "typography"
				}
			]
		},
		{
			"children": [
				{
					"children": [
						{
							"children": [
								{
									"detail": 0,
									"format": 0,
									"mode": "normal",
									"style": "",
									"text": "left",
									"type": "text",
									"version": 1
								}
							],
							"direction": "ltr",
							"format": "",
							"indent": 0,
							"type": "paragraph-element",
							"version": 1,
							"textFormat": 0,
							"styles": [
								{
									"styleId": "paragraph1",
									"type": "typography"
								}
							]
						}
					],
					"direction": "ltr",
					"format": "",
					"indent": 0,
					"type": "layout-item",
					"version": 1
				},
				{
					"children": [
						{
							"children": [
								{
									"detail": 0,
									"format": 0,
									"mode": "normal",
									"style": "",
									"text": "right",
									"type": "text",
									"version": 1
								}
							],
							"direction": "ltr",
							"format": "",
							"indent": 0,
							"type": "paragraph-element",
							"version": 1,
							"textFormat": 0,
							"styles": [
								{
									"styleId": "paragraph1",
									"type": "typography"
								}
							]
						}
					],
					"direction": "ltr",
					"format": "",
					"indent": 0,
					"type": "layout-item",
					"version": 1
				}
			],
			"direction": "ltr",
			"format": "",
			"indent": 0,
			"type": "layout-container",
			"version": 1,
			"templateColumns": "1fr 3fr"
		},
		{
			"children": [],
			"direction": null,
			"format": "",
			"indent": 0,
			"type": "paragraph-element",
			"version": 1,
			"textFormat": 0,
			"styles": [
				{
					"styleId": "paragraph1",
					"type": "typography"
				}
			]
		}
	]
}```
@bschulz87
Copy link
Author

bschulz87 commented Nov 12, 2024

So far i have managed to at least display the saved data by using a custom renderer like this:

import {RichTextLexicalRenderer} from "@webiny/react-rich-text-lexical-renderer";

{
    type: "cms-content-form-renderer",
    modelId: "page",
    render(props) {
        return <RichTextLexicalRenderer value={ props.data?.content} nodes={[LayoutContainerNode, LayoutItemNode,]} />
    }
 }

This way i have lost the form layout, though and the content is also not editable anymore.

@Pavel910
Copy link
Collaborator

Pavel910 commented Nov 12, 2024

@bschulz87 Headless CMS has its own Lexical config: https://www.webiny.com/docs/headless-cms/extending/lexical-editor, which is only applied to CMS context. Page Builder has its own, etc. So you basically did everything right, but you need to import the LexicalEditorConfig from the right package, so it is targeting Headless CMS specifically.

Btw. cms-content-form-renderer is a different thing, it's for rendering the whole form, field by field, in a custom layout. See the docs (but this is not what you need).

@bschulz87
Copy link
Author

Thank you @Pavel910. I now have added the Custom Nodes to LexicalEditorConfig from ""@webiny/app-headless-cms" and "@webiny/app-page-builder". It's still not showing up. I guess the nodes are fine since they show up when using the RichTextLexicalRenderer.

import { LexicalEditorConfig } from "@webiny/app-headless-cms";
import { LexicalEditorConfig as LexicalEditorConfigAppPageBuilder } from "@webiny/app-page-builder";
import { InsertColumnsPlugin } from "./plugins/headlessCMS/lexical/plugins/InsertColumnsPlugin";
import { InsertColumnsAction } from "./plugins/headlessCMS/lexical/actions/insertColumns";
import { LayoutContainerNode } from "./plugins/headlessCMS/lexical/nodes/LayoutContainerNode";
import { LayoutItemNode } from "./plugins/headlessCMS/lexical/nodes/LayoutItemNode";

const { ToolbarAction, Plugin, Node, } = LexicalEditorConfig;

export const App = () => {
    return (
        <Admin>
            <Cognito />
            <Extensions />
            <LexicalEditorConfig>
                <Plugin name={"insertColumns"} element={<InsertColumnsPlugin />} />
                <ToolbarAction name={"insertColumns"} element={<InsertColumnsAction />} />
                <Node name={"layoutContainerNode"} node={LayoutContainerNode} />
                <Node name={"layoutItemNode"} node={LayoutItemNode} />
            </LexicalEditorConfig>
            <LexicalEditorConfigAppPageBuilder>
                <LexicalEditorConfigAppPageBuilder.Heading.Node name={"layoutContainerNode"} node={LayoutContainerNode} />
                <LexicalEditorConfigAppPageBuilder.Heading.Node name={"layoutItemNode"} node={LayoutItemNode} />
                <LexicalEditorConfigAppPageBuilder.Paragraph.Node name={"layoutContainerNode"} node={LayoutContainerNode} />
                <LexicalEditorConfigAppPageBuilder.Paragraph.Node name={"layoutItemNode"} node={LayoutItemNode} />
            </LexicalEditorConfigAppPageBuilder>
        </Admin>
    );
};

@Pavel910
Copy link
Collaborator

Pavel910 commented Nov 13, 2024

@bschulz87 you keep mentioning RichTextLexicalRenderer, I don't understand where are you trying to render this?
P.S. join our Slack, it will be faster to have a chat there.

Also, if it's not a secret, can you share the code of your nodes? Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants