GrapesJS特性在重新加载编辑器后不显示。

huangapple go评论76阅读模式
英文:

GrapesJS trait does not appear after reloading the editor

问题

我有一个React网页应用程序(使用TypeScript,如果有关系)我正在尝试将GrapesJS HTML编辑器集成到其中。
它呈现在一个功能组件中,该组件会随着外部依赖项的更新而更新,从而刷新编辑器。

在其中定义了一个block,并定义了一个trait,当添加或选择按钮时,该trait会出现在编辑器的设置面板中,并且它也作为项目数据的一部分保存了下来。
然而,出于任何原因重新加载编辑器后,设置面板将不再显示该trait,而是恢复为默认的id, title traits:

GrapesJS特性在重新加载编辑器后不显示。

这是组件代码:

import React, { useEffect, useRef } from 'react';
import grapesjs, { Editor } from 'grapesjs';
import store, { StoreActions } from '../../state/store';
import { useCurrentPage } from '../ReactUtils';
import { useTypedDispatch } from '../../state/hooks';

export default function GrapesEditorWindow(props: any) 
{
	// ...(中文代码省略)...

	return <div id={"gjs"} ref={grapesEditorContainerRef} />;
}

这是存储数据(请注意,组件具有名为option-value的属性,其值已设置):

//...
components: [
  {
    tagName: 'button',
    name: 'Button',
    content: 'Click Me',
    attributes: {
      id: 'ija4',
      'option-value': '2'
    }
  }
]
//...

我尝试找出可能的问题所在,并遇到了这个帖子:https://github.com/GrapesJS/grapesjs/issues/2106 我尝试以相同的方式实现trait,使用TraitManager,但结果相同(重新加载编辑器后trait不显示):

//...
blocks: [
  {
    label: 'Button',
    content: {
      tagName: 'button',
      name: "Button",
      content: "Click Me",
      traits: [
        {
          label: 'Value',
          name: 'option-value',
          type: 'my-option-value',
        }
      ],
    },
  },
],

//...
editor.TraitManager.addType('my-option-value', {
  createInput({ trait }) 
  {
    const el = document.createElement('select');
    el.innerHTML = `
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>`;
    return el;
  }
});
//...

我还遇到了这个帖子,它建议将块编写为插件:https://github.com/GrapesJS/grapesjs/issues/2136 但这也导致了相同的结果(重新加载编辑器后trait不显示):

// 不同的文件
import { Plugin } from 'grapesjs';

export const gjsplugin: Plugin<any> = (editor, opts = {}) => 
{
	const blockManager = editor.BlockManager;

	blockManager.add('my-button', 
	{
		label: 'My Button',
		content: {
			type: 'button',
			tagName: 'button',				
			traits: [
				{
					label: 'Value',
					name: 'option-value',
					type: 'select',
					options: [
						{ value: '1' },
						{ value: '2' },
						{ value: '3' },
					],
				}
			],
		}
	});
}

export default gjsplugin;

// 主文件
//...
import gjsplugin from './gjsplugin';
//...
const editor = grapesjs.init({
	container: containerElement,
	storageManager: false,			
	blockManager: {
		appendOnClick: true,
	},
	plugins: [
		gjsplugin,
	],
	deviceManager: {
		devices: [
			{
				name: 'Desktop',
				width: '1920',
				height: '1200',
			},
		],
	},
});
//...

到目前为止,我尝试的一切都没有奏效,重新加载后trait从未显示在编辑器中。
我一定是做错了些什么,因为traits对于内部块类型(如video)或导入现有插件(如GrapesJS Forms)有效,但我无法弄清楚到底是什么问题。

英文:

I have a React web app (using TypeScript, if it matters) that I'm trying to integrate GrapesJS html editor into.
It's rendered in a functional component that gets updated with external dependencies, refreshing the editor.

There is a defined block with a defined trait and that trait appears in the editor's Settings panel when adding or selecting the button, and it's also saved as part of the project data.
However, when reloading the editor for any reason, the Settings panel no longer displays the trait, instead reverting back to the default id, title traits:
GrapesJS特性在重新加载编辑器后不显示。

This is the component code:

import React, { useEffect, useRef } from &#39;react&#39;;
import grapesjs, { Editor } from &#39;grapesjs&#39;;
import store, { StoreActions } from &#39;../../state/store&#39;;
import { useCurrentPage } from &#39;../ReactUtils&#39;;
import { useTypedDispatch } from &#39;../../state/hooks&#39;;

export default function GrapesEditorWindow(props: any) 
{
	const currentPage = useCurrentPage(); // this hook causes the component to re-render 
	const dispatch = useTypedDispatch();

	const grapesEditorContainerRef = useRef&lt;HTMLDivElement&gt;(null);
	const grapesEditor = useRef&lt;Editor&gt;();

	useEffect(() =&gt; 
	{
		return () =&gt; grapesEditor.current?.destroy();
	}, []);

	useEffect(() =&gt; 
	{
		if (grapesEditorContainerRef.current) 
		{
			grapesEditor.current = createGrapesEditor(grapesEditorContainerRef.current);
			grapesEditor.current.loadProjectData(store.getState().gjsModule.pageUIData[currentPage.id]);
		}
	}, [grapesEditorContainerRef.current, currentPage]);

	function createGrapesEditor(containerElement: HTMLDivElement): Editor
	{
		const editor = grapesjs.init({
			container: containerElement,
			storageManager: false,			
			blockManager: {
				appendOnClick: true,
				blocks: [
					{
						label: &#39;Button&#39;,
						content: {
							tagName: &#39;button&#39;,
							name: &quot;Button&quot;,
							content: &quot;Click Me&quot;,
							traits: [
								{
									label: &#39;Value&#39;,
									name: &#39;option-value&#39;,
									type: &#39;select&#39;,
									options: [
										{ value: &quot;1&quot; },
										{ value: &quot;2&quot; },
										{ value: &quot;3&quot; },
									],
								}
							],
						},
					},
				],
			},
			deviceManager: {
				devices: [
					{
						name: &#39;Desktop&#39;,
						width: &#39;1920&#39;,
						height: &#39;1200&#39;,
					},
				],
			},
		});

		editor.on(&#39;update&#39;, function()
		{
			const data = grapesEditor.current?.getProjectData();
			dispatch(StoreActions.gjs.setPageUIData({ pageId: currentPage.id, data: data }));
		});
		
		return editor;
	}

	return &lt;div id={&quot;gjs&quot;} ref={grapesEditorContainerRef} /&gt;;
}

And this is the store data (note that the component has an attribute named option-value and its value is set):

//...
              components: [
                {
                  tagName: &#39;button&#39;,
                  name: &#39;Button&#39;,
                  content: &#39;Click Me&#39;,
                  attributes: {
                    id: &#39;ija4&#39;,
                    &#39;option-value&#39;: &#39;2&#39;
                  }
                }
              ]
//...

I've tried to find out what could be the problem, and encountered this thread: https://github.com/GrapesJS/grapesjs/issues/2106 I've tried to implement the trait in the same way, using TraitManager, with the same result (trait does not show after editor reload):

//...
blocks: [
					{
						label: &#39;Button&#39;,
						content: {
							tagName: &#39;button&#39;,
							name: &quot;Button&quot;,
							content: &quot;Click Me&quot;,
							traits: [
								{
									label: &#39;Value&#39;,
									name: &#39;option-value&#39;,
									type: &#39;my-option-value&#39;,
								}
							],
						},
					},
				],

//...
editor.TraitManager.addType(&#39;my-option-value&#39;, {
			createInput({ trait }) 
			{
				const el = document.createElement(&#39;select&#39;);
				el.innerHTML = `
					&lt;option value=&quot;1&quot;&gt;1&lt;/option&gt;
					&lt;option value=&quot;2&quot;&gt;2&lt;/option&gt;
					&lt;option value=&quot;3&quot;&gt;3&lt;/option&gt;`;
				return el;
			}
		});
//...

I've also come across this thread, which suggest writing the block as a plugin instead: https://github.com/GrapesJS/grapesjs/issues/2136
But that too has the same result (trait not showing after editor reload):

// different file
import { Plugin } from &#39;grapesjs&#39;;

export const gjsplugin: Plugin&lt;any&gt; = (editor, opts = {}) =&gt; 
{
	const blockManager = editor.BlockManager;

	blockManager.add(&#39;my-button&#39;, 
		{
			label: &#39;My Button&#39;,
			content: {
				type: &#39;button&#39;,
				tagName: &#39;button&#39;,				
				traits: [
					{
						label: &#39;Value&#39;,
						name: &#39;option-value&#39;,
						type: &#39;select&#39;,
						options: [
							{ value: &#39;1&#39; },
							{ value: &#39;2&#39; },
							{ value: &#39;3&#39; },
						],
					}
				],
			}
		});
}

export default gjsplugin;

// main file
//...
import gjsplugin from &#39;./gjsplugin&#39;;
//...
const editor = grapesjs.init({
			container: containerElement,
			storageManager: false,			
			blockManager: {
				appendOnClick: true,
			},
			plugins: [
				gjsplugin,
			],
			deviceManager: {
				devices: [
					{
						name: &#39;Desktop&#39;,
						width: &#39;1920&#39;,
						height: &#39;1200&#39;,
					},
				],
			},
		});
//...

So far, nothing I've tried worked, and the traits never show in the editor after a reload.
I must be doing something wrong as traits work for internal block types like video or when importing existing plugins such as GrapesJS Forms, but I can't figure out what exactly.

答案1

得分: 1

在我的情况下,当我使用Vue和Laravel实现从数据库保存/恢复数据时,我遇到了相同的问题。

我看到你尝试将它制作成插件,对我来说有效,我唯一看到你的代码和我的代码之间的区别是你添加类型的位置:

editor.TraitManager.addType('my-option-value', {
    createInput({ trait }) {
        const el = document.createElement('select');
        el.innerHTML = `
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>`;
        return el;
    }
});

相反,我将类型添加到DomComponents,所以你的代码应该是:

function pluginName(editor){
    editor.DomComponents.addType(...your code)
}

然后在初始化GrapesJS时在你的插件列表中使用它。

希望它能起作用!

英文:

in my case I was having the same problem when implementing it with Vue and Laravel saving/restoring data from the database.

I see you tried to make it a plugin, that worked for me, only difference I can see between your code and mine is where you add the type

editor.TraitManager.addType(&#39;my-option-value&#39;, {
        createInput({ trait }) 
        {
            const el = document.createElement(&#39;select&#39;);
            el.innerHTML = `
                &lt;option value=&quot;1&quot;&gt;1&lt;/option&gt;
                &lt;option value=&quot;2&quot;&gt;2&lt;/option&gt;
                &lt;option value=&quot;3&quot;&gt;3&lt;/option&gt;`;
            return el;
        }
    });

Instead, I add the type in DomComponents, so your code would be

function pluginName(editor){
    editor.DomComponents.addType(...your code)
}

And then in your plugins list when initializing GrapesJS.

Hope it works!

huangapple
  • 本文由 发表于 2023年6月29日 16:30:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76579325.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定