Issue #3512Opened June 2, 2021by Palash-Mandal1 reactions

BUG: Child elements not draggable ,droppable highlightable. also the CSS of all child elements not pushed in style section while develop a banner component in as plugin

Question

Hello @artf ,

I am trying to develop a simple banner plugin which will be include a heading , subheading and link. and every element can be draggable ,droppable highlightable, but based on below code some portion of code not working. Please Help

image

only banner class CSS pushed but another all not go in the CSS section image

Code SnippetTEXT
------------ index.js----------

![image](https://user-images.githubusercontent.com/17553816/120481948-46985600-c3ce-11eb-8239-7f1d28242320.png)


import loadComponents from './components';
import loadBlocks from './blocks';

export default (editor, opts = {}) => {
    const options = {... {
            // default options
            bannerBlock: {},
            classBanner: "banner",
            template: `
            <div><h2 class="banner__heading">Banner Heading</h2></div>
            <div> <h3 class="banner__subheading">Banner Sub heading</h3></div>
            <div> <a class="banner__link" href="#">Get Started</a></div>
            `,
            style: `
          .banner {
            background-color: #c9efff;
            background-repeat: no-repeat;
            background-position: center center;
            background-size: cover;
            position: relative;
            padding: 80px 20px;
            border-radius:0;
            display: flex;
            align-items: center;
            justify-content: center;
            flex-direction: column;
            min-height: 370px;
          }

          .banner__heading {
            font-weight: 700;
            color: #333;
            font-size: 40px;
            margin-bottom: 16px;
            text-align: center;
            line-height: 1.2;
          }
          .banner__subheading {
            font-size: 26px;
            text-align: center;
            margin-top: 16px;
            font-weight: 500;
            color: #333;
          }
          .banner__link {
            display: block;
            padding: 10px 20px;
            background: none;
            margin: 5px;
            font-size: 14px;
            color: #fff !important;
            background-color: #005A9E;
            transition: all 0.2s ease-in;
            border-radius: 4px;
            font-weight: 500;
            border: none !important;
            text-align: center;
            min-width: 160px;
            letter-spacing: 1px;
          }
        `,
        },
        ...opts
    };

    // Add components
    loadComponents(editor, options);
    // Add blocks
    loadBlocks(editor, options);
};

------------- Block JS-------------
![image](https://user-images.githubusercontent.com/17553816/120482131-70ea1380-c3ce-11eb-9624-700c200e45dc.png)

export default (editor, config = {}) => {
    const bm = editor.BlockManager;
    const bannerBlock = config.bannerBlock;
    const style = config.style;
    const type = "bannerblock";
    const content = `<div data-gjs-type="${type}"></div>
  ${style ? `<style>${style}</style>` : ""}`;

  bannerBlock &&
  bm.add(type, {
    label: "Banner",
    category: 'Components',
    attributes: { class: "fa fa-list" },
    activate: 1,
    select: 1,
    removable: true, // Can't remove it
    draggable: true, // Can't move it
    copyable: true, // Disable copy/past
    content,
    ...bannerBlock,
  });
}

----------- Component JS------------
![image](https://user-images.githubusercontent.com/17553816/120482266-9414c300-c3ce-11eb-9132-2dad65d2d392.png)
export default (editor, config = {}) => {
    const domc = editor.DomComponents;
    const type = 'bannerblock';
    const classbanner = config.classBanner;
    domc.addType(type, {
        model: {
            defaults: {
                attributes: { class: classbanner },
                content: config.template,
                draggable: true,
                droppable: true,
                copyable: true,
                removable: true,
                selectable: true,
            },
        },
        view: {

        },
    });
};

Answers (2)

artfJuly 6, 20211 reactions

In your model component definition, you're using content: config.template but it should be components: config.template

Palash-MandalJune 15, 20210 reactions

Hello @artf ,

I have made the solution but there are some issue arise the component. the child component h2,h3 and link pushed for all other component. If I drop one column component those child element also pushed inside there. How Do I restrict the conflict. Below here is the codepen example where I made a demo. https://codepen.io/coderdesigners/full/XWMoNbZ

If I drop one column the below com up. which is not expected. it should as per default. image

When drop the banner component. image

Please Please help this. I know I have some silly mistake which is I unable to under stand. I am sorry for bother you.

Thanks in Advance.

And here is my plugin details

image export default { // Object to extend the default banner block, eg. { label: 'Banner', attributes: { ... } } // Pass a falsy value to avoid adding the block bannerBlock: {},

// Object to extend the default Banner properties, eg. `{ name: 'My Banner', droppable: false, ... }`
bannerCreateProps: {},

// Object to extend the default heading properties
bannerHeadingProps: {},

// Object to extend the default Sub heading properties
bannerSubHeadingProps: {},

// Object to extend the default button properties
bannerButtonProps: {},


// Tabs component id
typeBanner: 'banner',

// TabContainer component id
typeBannerHeading: 'Banner-Heading',

// Tab component id
typeBannerSubHeading: 'Banner-SubHeading',

// TabContent component id
typeBannerButton: 'Banner-Button',

// Default class to use on Banner
classBannerContainer: 'zslbanner',

// Default class to use on Banner
classHeading: 'zslbanner__heading',
Code SnippetTEXT
// Default class to use on Banner
    classSubHeading: 'zslbanner__subheading',

    // Default class to use on Banner
    classLink: 'zslbanner__link',

    // Default style for tabs
    style: (config) => `
        .${config.classBannerContainer} {
        font-family: 'Montserrat', Arial, sans-serif;
        background-color: #c9efff;
        background-repeat: no-repeat;
        background-position: center center;
        background-size: cover;
        position: relative;
        padding: 80px 20px;
        border-radius:0;
        display: flex;
        align-items: center;
        justify-content: center;
        flex-direction: column;
        min-height: 370px;
      }
      .${config.classHeading} {
        font-weight: 700;
        color: #333;
        font-size: 40px;
        margin:0;
        margin-bottom: 16px;
        text-align: center;
        line-height: 1.2;
      }
      .${config.classSubHeading} {
        font-size: 26px;
        text-align: center;
        margin:0;
        margin-bottom: 16px;
        font-weight: 500;
        color: #333;
      }
      .${config.classLink} {
        display: block;
        padding: 10px 20px;
        background: none;
        margin: 20px 5px 5px 0 5px;
        font-size: 14px;
        color: #fff !important;
        background-color: #005A9E;
        transition: all 0.2s ease-in;
        border-radius: 4px;
        font-weight: 500;
        border: none !important;
        text-align: center;
        min-width: 160px;
        letter-spacing: 1px;
      }
      .${config.classLink}:hover {
        background-color: #037ede;  
       }
 `
}
![image](https://user-images.githubusercontent.com/17553816/122001932-b6471180-cdce-11eb-822f-f81f75af60ef.png)

![image](https://user-images.githubusercontent.com/17553816/122001962-c3640080-cdce-11eb-877a-56108e2adbba.png)

![image](https://user-images.githubusercontent.com/17553816/122001992-cfe85900-cdce-11eb-8b1b-6c3fe60ee60f.png)

**Subheading.js**
export const role = 'SubHeading';

export default (dc, config) => {

    dc.addType(config.typeBannerSubHeading, {
        model: {
            isComponent: function(t) {
                return ['H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'p'].indexOf(t.tagName) >= 0
            },
            defaults: {
                name: 'Sub Heading',
                draggable: true,
                copyable: true,
                removable: true,
                highlightable: true,
                editable: true,
                attributes: { role },
                classes: config.classSubHeading,
                tagName: 'h3',
                content: 'Sub Heading',
                traits: [
                    'id',
                    'title',
                    {
                        type: "select",
                        options: [{
                            value: "h1",
                            name: "Heading 1"
                        }, {
                            value: "h2",
                            name: "Heading 2"
                        }, {
                            value: "h3",
                            name: "Heading 3"
                        }, {
                            value: "h4",
                            name: "Heading 4"
                        }, {
                            value: "h5",
                            name: "Heading 5"
                        }, {
                            value: "h6",
                            name: "Heading 6"
                        }, {
                            value: "p",
                            name: "Paragraph"
                        }],
                        label: "Heading Or paragraph",
                        name: "tagName",
                        changeProp: 1
                    }
                ],
                ...config.bannerSubHeadingProps
            },
        },
        view: {
            events: {
                dblclick: 'onActive',
                focusout: 'onDisable',
            },
            onActive() {
                this.el.contentEditable = true;
            },
            onDisable() {
                const { el, model } = this;
                // el.contentEditable = false;
                model.set('content', el.innerHTML)
            },
        }
    });
}
![image](https://user-images.githubusercontent.com/17553816/122002066-e55d8300-cdce-11eb-8216-e91659cfaaad.png)

![image](https://user-images.githubusercontent.com/17553816/122002133-fad2ad00-cdce-11eb-9aab-d3f02d37c78b.png)

**Heading.js**

export const role = 'Heading';

export default (dc, config) => {

    dc.addType(config.typeBannerHeading, {
        model: {
            isComponent: function(t) {
                return ['H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'p'].indexOf(t.tagName) >= 0
            },
            defaults: {
                name: 'Heading',
                draggable: true,
                copyable: true,
                removable: true,
                highlightable: true,
                editable: true,
                attributes: { role },
                classes: config.classHeading,
                tagName: 'h2',
                components: 'Heading',
                traits: [
                    'id',
                    'title',
                    {
                        type: "select",
                        options: [{
                            value: "h1",
                            name: "Heading 1"
                        }, {
                            value: "h2",
                            name: "Heading 2"
                        }, {
                            value: "h3",
                            name: "Heading 3"
                        }, {
                            value: "h4",
                            name: "Heading 4"
                        }, {
                            value: "h5",
                            name: "Heading 5"
                        }, {
                            value: "h6",
                            name: "Heading 6"
                        }, {
                            value: "p",
                            name: "Paragraph"
                        }],
                        label: "Heading Or paragraph",
                        name: "tagName",
                        changeProp: 1
                    }
                ],
                ...config.bannerHeadingProps
            },
        },
        view: {
            events: {
                dblclick: 'onActive',
                focusout: 'onDisable',
            },
            onActive() {
                this.el.contentEditable = true;
            },
            onDisable() {
                const { el, model } = this;
                el.contentEditable = false;
                model.set('content', el.innerHTML)
            },
        }
    });
}

**Button.js**
export default (dc, config) => {

    dc.addType(config.typeBannerButton, {
        model: {
            extend: 'link',
            defaults: {
                editable: true,
                name: 'Button',
                draggable: true,
                copyable: true,
                removable: true,
                highlightable: true,
                attributes: {
                    href: '#'
                },
                classes: config.classLink,
                content: 'Get Started',
                tagName: 'a',
                traits: [
                    'id',
                    'title',
                    'href',
                    'target',
                ],
                ...config.bannerButtonProps
            },
        },
        view: {
            events: {
                dblclick: 'onActive',
                focusout: 'onDisable',
            },
            onActive() {
                this.el.contentEditable = true;
            },
            onDisable() {
                const { el, model } = this;
                el.contentEditable = false;
                model.set('content', el.innerHTML)
            },
        }
    });
}


**BannerCreate.js**
export default (dc, {
    typeBanner,
    typeBannerHeading,
    typeBannerSubHeading,
    typeBannerButton,
    style,
    ...config
}) => {
    const type = config.typeBanner;
    dc.addType(type, {
        model: {
            defaults: {
                name: 'Banner',
                classes: config.classBannerContainer,
                components: [
                    { type: typeBannerHeading },
                    { type: typeBannerSubHeading },
                    { type: typeBannerButton },
                    style && `<style>${style(config)}</style>`
                ],
                ...config.bannerCreateProps
            },
        },
    });
}

Please Help.

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.