GrapesJS / grapesjs

Free and Open source Web Builder Framework. Next generation tool for building templates without coding
https://grapesjs.com
BSD 3-Clause "New" or "Revised" License
22.36k stars 4.05k forks source link

[BUG] Component from custom plugin is not recognized #1896

Closed kaoz70 closed 5 years ago

kaoz70 commented 5 years ago

OS: Windows 10 x64 Browser: Chrome 72.0.3626.121 x64 GrapesJS: v0.14.55

Hello, I have some custom components (bootstrap tabs) in a plugin, for some reason some of the components of the plugin are not being detected by GrapesJS when loading it from the container elements, and others via dragging and dropping into the editor.

This Component is not being detected:

const defaultType = dc.getType('default');
const defaultModel = defaultType.model;
const defaultView = defaultType.view;
const {tabPanesName, tabPaneSelector} = constants;
const classId = config.classTabPanes;
const type = tabPanesName;

dc.addType(type, {

    model: defaultModel.extend({
        defaults: {
            ...defaultModel.prototype.defaults,
            name: 'Tab Content',
            copyable: 0,
            draggable: true,
            droppable: tabPaneSelector,
        },
    }, {
        isComponent(el) {
            if (elHasClass(el, 'tab-content')) {
                return {type};
            }
        },
    }),

    view: {removed because too big for issue},
});

But this one is:

const defaultType = dc.getType('default');
const defaultModel = defaultType.model;
const defaultView = defaultType.view;
const { navigationName, tabSelector } = constants;
const type = navigationName;

dc.addType(type, {

    model: defaultModel.extend({
        defaults: {
            ...defaultModel.prototype.defaults,
            name: 'Navigation',
            copyable: 0,
            draggable: true,
            droppable: tabSelector,

            traits: [
                {
                    type: 'class_select',
                    options: [
                        {value: 'nav-tabs', name: 'Tabs'},
                        {value: 'nav-pills', name: 'Pills'},
                    ],
                    label: 'Type',
                },
                {
                    type: 'class_select',
                    options: [
                        {value: '', name: 'Left'},
                        {value: 'nav-fill', name: 'Fill'},
                        {value: 'nav-justified', name: 'Justify'},
                    ],
                    label: 'Layout',
                },
            ],
        },
    }, {
        isComponent(el) {
            if (el.className && el.getAttribute('role') === 'tablist') {
                return {type};
            }
        },
    }),

    view: {removed because too big for issue},
});

Init code

var editor = grapesjs.init({
    height: '100%',
    showOffsets: 1,
    noticeOnUnload: 0,
    storageManager: { autoload: 0 },
    container: '#gjs',
    fromElement: true,
    showDevices: false,
    plugins: ['grapesjs-blocks-bootstrap4'],
    pluginsOpts: {
      'grapesjs-blocks-bootstrap4': {
        blocks: {},
        blockCategories: {},
        labels: {},
        gridDevicesPanel: true,
        formPredefinedActions: [
          {name: 'Contact', value: '/contact'},
          {name: 'landing', value: '/landing'},
        ]
      }
    },
    canvas: {
      styles: [
        'https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css'
      ],
      scripts: [
        'https://code.jquery.com/jquery-3.3.1.slim.min.js',
        'https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js',
        'https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js'
      ],
    }
  });
  window.editor = editor;

HTML

This is the HTML thats inside the #gjs element and that GrapesJS should parse into components:

<div class="container">

    <!-- Tab navigation -->
    <ul class="nav nav-tabs" role="tablist">
      <li class="nav-item">
        <a class="nav-link active" data-toggle="tab" href="#home" role="tab">Home</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" data-toggle="tab" href="#profile" role="tab">Profile</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" data-toggle="tab" href="#messages" role="tab">Messages</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" data-toggle="tab" href="#settings" role="tab">Settings</a>
      </li>
    </ul>
    <!-- Tab panes -->
    <div class="tab-content">
      <div class="tab-pane active" id="home" role="tabpanel">Home</div>
      <div class="tab-pane" id="profile" role="tabpanel">Profile</div>
      <div class="tab-pane" id="messages" role="tabpanel">Messages</div>
      <div class="tab-pane" id="settings" role="tabpanel">Settings</div>
    </div>

  </div>

</div>

Problem

The problem seems to be in the isComponent(el) method, the "el" parameter is never that particular element so it never returns the valid type.

What could the issue be?

artf commented 5 years ago

It might be that elHasClass method?!?

kaoz70 commented 5 years ago

Sorry if I was not too clear, even if I just do a:

isComponent(el) {
    console.log(el);
}

That specific element is not printed.

artf commented 5 years ago

Well, it seems like it's not yet added when the parser processes the string... Are you adding that component after the initialization?

kaoz70 commented 5 years ago

No, that component is taken from the current HTML of the element where I instantiate the editor on, as you can see from the init configuration.

On Sun, Mar 24, 2019, 15:38 Artur Arseniev notifications@github.com wrote:

Well, it seems like it's not yet added when the parser processes the string... Are you adding that component after the initialization?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/artf/grapesjs/issues/1896#issuecomment-475997591, or mute the thread https://github.com/notifications/unsubscribe-auth/AAE2LhGTiNMRlznlCudGAEFHCK0PcVEGks5vZ-I4gaJpZM4b3a6M .

artf commented 5 years ago

No, I'm asking if you declare that component (dc.addType(type, {...) after initialization of the editor (editor.init({...)

kaoz70 commented 5 years ago

Oh, I'm declaring that component inside a plug-in ( grapesjs-blocks-bootstrap4) so it should be a available during the parse.

On Sun, Mar 24, 2019, 16:14 Artur Arseniev notifications@github.com wrote:

No, I'm asking if you declare that component (dc.addType(type, {...) after initialization of the editor (editor.init({...)

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/artf/grapesjs/issues/1896#issuecomment-476000788, or mute the thread https://github.com/notifications/unsubscribe-auth/AAE2LvMwSTGsj7Y9oD_nA9LLe8bQnk8Nks5vZ-rKgaJpZM4b3a6M .

artf commented 5 years ago

Ah ok, in that case, you should report the issue to the author of the plugin...

kaoz70 commented 5 years ago

The original author transferred the plug-in repo to me, so technically I would be that person.

All the components are initialized in the same place so I don't think it should be a problem with the component being available after the parsing, but seems to be a problem with the parser.

In any case, is it possible to instantiate (erroneously) a component inside a plug-in after initializing the editor?

I will double check the script again just in case and update this issue accordingly.

On Sun, Mar 24, 2019, 16:31 Artur Arseniev notifications@github.com wrote:

Ah ok, in that case, you should report the issue to the author of the plugin...

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/artf/grapesjs/issues/1896#issuecomment-476002304, or mute the thread https://github.com/notifications/unsubscribe-auth/AAE2LnxiBq2G5KMzgQBl1C4f0N5MMioNks5vZ-68gaJpZM4b3a6M .

artf commented 5 years ago

The original author transferred the plug-in repo to me, so technically I would be that person.

Ah ok, good to know

In any case, is it possible to instantiate (erroneously) a component inside a plug-in after initializing the editor?

I'm not sure if I get your question correctly, but if you're asking about defining a new custom component not correctly I would say you should avoid doing this:

const myPlugin = editor => {
    // ... plugin content

    // Define new type correctly
    const domc = editor.DomComponents;
    domc.addType(...);

    editor.on('load', () => {
        // Wrong, this means that the new type will be available only
        // once all the content are loaded
        domc.addType(...);
        // so only new components (eg. dropped from blocks) will be seen
        // by this definition
    })
}
kaoz70 commented 5 years ago

Alright, so checking the code again, it seems the tabs are being set inside the plugin correctly:

grapesjs.plugins.add('grapesjs-blocks-bootstrap4', (editor, opts = {}) => {
    ...
    domc.addType('tabs-panes', {...}); // This one wont register
    domc.addType('tabs-navigation', {...}); // This one will
    ...
});

This is the result of doing the console.log, as you can see (if I'm correct) it seems to skip over the element that I need "div.tab-content" and goes directly to that element's child node "div#home.tab-pane.active":

image

artf commented 5 years ago

Are you sure .tab-content element is not captured by some other component? For example, try to select it and print editor.getSelected().get('type') in console

kaoz70 commented 5 years ago

This is the result:

image

This is the element: image

artf commented 5 years ago

As you see, its type is div... this is why it never reaches the other type... look why and where that type is declared

kaoz70 commented 5 years ago

Alright, that was the issue! I thought that the 'div' type was a default one set by GrapesJS. Thanks for all the help!

lock[bot] commented 4 years ago

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.