Issue #2831Opened June 15, 2020by mustahsanmustafa1 reactions

[BUG] Text components don't behave correctly after creating custom components

Question

Hi artf,

After creating custom components, the text component does not behave like before. It removes all the naked nodes after changing some code in import modal. e.g

<div>Insert your text 
        <a data-cke-saved-href="http://abc" href="http://abc">here</a>
</div>

After editing something in import modal it gets change to:

<div>
        <a data-cke-saved-href="http://abc" href="http://abc">here</a>
</div>

As you can see it removed the Naked text node i.e Insert your text. It should be noted that this behavior doesnt happen when there is no custom component added to the editor.

An example of custom component that i created:

export const NavbarMenu = editor => {
	var defaultType = editor.DomComponents.getType("default");
	var defaultModel = defaultType.model;
	editor.DomComponents.addType('menu-nav', {
		isComponent: el => el.tagName === 'menu-nav',
		model: defaultModel.extend({
			// Extend default properties
			defaults: Object.assign({}, defaultModel.prototype.defaults, {
				tagName: 'menu-nav',
				removable: true,
				copyable: false,
				droppable: false,
                resizable: false,
				editable: false,
				traits: [
                    {
                        type: 'text',
                        name: 'menuName',
                        label: 'Menu Name'
                    }
                ],
				attributes: {
                    'menuName': 'Header Nav'
				},
				propagate: ['removable', 'droppable', 'copyable', 'editable'],
				components: `
<div data-gjs-selectable="false" class="container-fluid bg-menu">
  <div class="row" data-gjs-selectable="false">
    <div class="col-lg-12" data-gjs-selectable="false">
      <div class="main-nav-center" data-gjs-selectable="false">
        <nav id="main-nav" class="prvidr-navbar-menu text-center" data-gjs-selectable="false">
          <ul id="main-menu" class="sm pixelstrap sm-horizontal catch-menu" data-gjs-selectable="false">
            <li data-gjs-selectable="false">
              <a data-gjs-selectable="false" href="javascript:void(0)">
                Menu Item 1
              </a>
            </li>
            <li data-gjs-selectable="false">
              <a data-gjs-selectable="false" href="javascript:void(0)">
                Menu Item 2
              </a>
            </li>
            <li data-gjs-selectable="false">
              <a data-gjs-selectable="false" href="javascript:void(0)">
                Menu Item 3
              </a>
            </li>
            <li data-gjs-selectable="false">
              <a data-gjs-selectable="false" href="javascript:void(0)">
                Menu Item 4
              </a>
            </li>
          </ul>
        </nav>
      </div>
    </div>
  </div>
</div>
				`
			}),
			init(){
				var props = this.getAttributes().props;
				if (props) {
					props = JSON.parse(props);
					this.addAttributes({'menuName':props['menuName']});
				}
			},
			toHTML: function () {
			    let props:any = {};
			    props['menuName'] = this.getAttributes().menuName;
				return `<menu-nav data-gjs-type="menu-nav" props='${JSON.stringify(props)}'></menu-nav>`
			}

		})
	});

	editor.BlockManager.add('menu-nav', {
		label: 'Header Menu',
		attributes: {
			class: 'fa fa-bars'
		},
		category: {
			label: "Dynamic Menu"
		},
		content: {
			type: 'menu-nav'
		}
	});
}

Answers (2)

artfJune 18, 20201 reactions

You're mixing the old API with the new one for the custom component definition. With model: defaultModel.extend({ was required an inner static isComponent (you're using one outside, like in the new API) and without it, you're breaking the Component Type Stack

You should just change model: defaultModel.extend({...}) to model: {...} but in your case, I'd also suggest reading carefully https://grapesjs.com/docs/modules/Components.html

mustahsanmustafaJune 15, 20200 reactions

UPDATE:

If i just extend my custom components from textnode instead of default, then the issue gets resolved somehow:

export const NavbarMenu = editor => {
	var defaultType = editor.DomComponents.getType("textnode"); //<-- changed to textnode
	var defaultModel = defaultType.model;
	editor.DomComponents.addType('menu-nav', {
		isComponent: el => el.tagName === 'menu-nav',
		model: defaultModel.extend({
                ......

but it will be better if the issue is resolved at default as well. cheers

Related Questions and Answers

Continue research with similar issue discussions.

Paid Plugins That Match This Issue

Curated by issue keywords and label relevance to help you ship faster.

View all plugins

Loading paid plugin recommendations...

Browse Plugin Categories

Jump directly to plugin category pages on the marketplace.