Issue #3345Opened March 17, 2021by joshk1320 reactions

Panels and Buttons section of getting started not working with Vue.js

Question

I am working to get grapejs to work with Vue.js and am having no luck, I am following the getting started however I am unable to get it to work properly. So far I have added it to the mounted() section and have gotten some buttons with blocks to show up and add in however I have had no luck getting the Panels and Buttons section to work.

Issue TLDR: Using Vue.js I can't get the panels and buttons section from getting started to show.

Below I have included my entire App.vue file which is the main one I am trying to add it into at this time - proof of concept will move to a proper location later.

<template>
  <div class="base">
    <div class="panel__top">
      <div class="panel__basic-actions"></div>
    </div>
    <div id="gjs">
      <h1>Hello World Component!</h1>
    </div>
    <div id="blocks"></div>
    <link rel="stylesheet" href="//unpkg.com/grapesjs/dist/css/grapes.min.css">
  </div>
</template>

<script>
// import VueGrapesjs from 'vue-grapesjs'
import grapesjs from 'grapesjs'
export default {
  name: 'app',
  data () {
    return {

    }
  },
  mounted(){
    grapesjs.init({
      // Indicate where to init the editor. You can also pass an HTMLElement
      container: '#gjs',
      // Get the content for the canvas directly from the element
      // As an alternative we could use: `components: '<h1>Hello World Component!</h1>'`,
      fromElement: true,
      // Size of the editor
      height: '1000px',
      width: 'auto',
      // Disable the storage manager for the moment
      storageManager: false,
      // Avoid any default panel
      panels: { defaults: [] },
      // Allows creation of "blocks"
      blockManager: {
        appendTo: '#blocks',
        blocks: [
          {
            id: 'section', // id is mandatory
            label: '<b>Section</b>', // You can use HTML/SVG inside labels
            attributes: { class:'gjs-block-section' },
            content: `<section>
              <h1>This is a simple title</h1>
              <div>This is just a Lorem text: Lorem ipsum dolor sit amet</div>
            </section>`,
          }, {
            id: 'text',
            label: 'Text',
            content: '<div data-gjs-type="text">Insert your text here</div>',
          }, {
            id: 'image',
            label: 'Image',
            // Select the component once it's dropped
            select: true,
            // You can pass components as a JSON instead of a simple HTML string,
            // in this case we also use a defined component type `image`
            content: { type: 'image' },
            // This triggers `active` event on dropped components and the `image`
            // reacts by opening the AssetManager
            activate: true,
          }
        ]
      },
    });
    grapesjs.Panels.addPanel({
      id: 'panel-top',
      el: '.panel__top',
    });
    grapesjs.Panels.addPanel({
      id: 'basic-actions',
      el: '.panel__basic-actions',
      buttons: [
        {
          id: 'visibility',
          active: true, // active by default
          className: 'btn-toggle-borders',
          label: '<u>B</u>',
          command: 'sw-visibility', // Built-in command
        }, {
          id: 'export',
          className: 'btn-open-export',
          label: 'Exp',
          command: 'export-template',
          context: 'export-template', // For grouping context of buttons from the same panel
        }, {
          id: 'show-json',
          className: 'btn-show-json',
          label: 'JSON',
          context: 'show-json',
          command(editor) {
            editor.Modal.setTitle('Components JSON')
              .setContent(`<textarea style="width:100%; height: 250px;">
                ${JSON.stringify(editor.getComponents())}
              </textarea>`)
              .open();
          },
        }
      ],
    });
  }
}
</script>

<style>
#gjs {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
  border: 3px solid #444;
}

/* Reset some default styling */
.gjs-cv-canvas {
  top: 0;
  width: 100%;
  height: 100%;
}

.gjs-block {
  width: auto;
  height: auto;
  min-height: auto;
}

.panel__top {
  padding: 0;
  width: 100%;
  display: flex;
  position: initial;
  justify-content: center;
  justify-content: space-between;
}

.panel__basic-actions {
  position: initial;
}
</style>

Answers (3)

uchoaaaMarch 20, 20210 reactions

Take a look at this issue, maybe helps: https://github.com/artf/grapesjs/issues/275

<template>
    <div :id="id"></div>
</template>

<script>
    export default {
        props: {
            id: {
                type: String,
                required: true
            }
        },
        data() {
            return {
                editor: null
            }
        },
        methods: {
            change() {
                this.$emit('change', this.editor.getHtml());
            },
        },
        mounted() {
            this.editor = grapesjs.init({
                container: '#editor',
                height: this.height,
                plugins: ['gjs-preset-newsletter'],
            });

            this.editor.on('change', this.change);
        }
    }
</script>
artfMarch 23, 20210 reactions

Hi @joshk132 honestly the code looks good, are you able to create a reproducible demo (on something like Codesandbox)?

joshk132March 26, 20210 reactions

@artf I've gotten it working where the panels show up however it now doesn't display right. The solution I had to do was change to use the below code. Pretty much I had to have "editor" as a variable which I had removed in my initial code because the vue linter was complaining. Attached there is a link to an image of how it looks with the below code, I am unsure on what exactly is wrong to cause the style issues.

https://imgur.com/GuFqv0o

<template>
  <div class="base">
    <div class="panel__top">
      <div class="panel__basic-actions"></div>
      <div class="panel__switcher"></div>
    </div>
    <div class="panel__right">
      <div class="layers-container"></div>
      <div class="styles-container"></div>
    </div>
    <div id="gjs">
      <h1>Hello World Component!</h1>
    </div>
    <div id="blocks"></div>
    <link rel="stylesheet" href="https://unpkg.com/grapesjs/dist/css/grapes.min.css">
  </div>
</template>

<script>
// import VueGrapesjs from 'vue-grapesjs'
import grapesjs from 'grapesjs'
export default {
  name: 'app',
  data () {
    return {

    }
  },
  mounted(){
    const editor = grapesjs.init({
      // Indicate where to init the editor. You can also pass an HTMLElement
      container: '#gjs',
      // Get the content for the canvas directly from the element
      // As an alternative we could use: `components: '<h1>Hello World Component!</h1>'`,
      fromElement: true,
      // Size of the editor
      height: '1000px',
      width: 'auto',
      // Disable the storage manager for the moment
      storageManager: false,
     
      // Allows creation of "blocks"
      blockManager: {
        appendTo: '#blocks',
        blocks: [
          {
            id: 'section', // id is mandatory
            label: '<b>Section</b>', // You can use HTML/SVG inside labels
            attributes: { class:'gjs-block-section' },
            content: `<section>
              <h1>This is a simple title</h1>
              <div>This is just a Lorem text: Lorem ipsum dolor sit amet</div>
            </section>`,
          }, {
            id: 'text',
            label: 'Text',
            content: '<div data-gjs-type="text">Insert your text here</div>',
          }, {
            id: 'image',
            label: 'Image',
            // Select the component once it's dropped
            select: true,
            // You can pass components as a JSON instead of a simple HTML string,
            // in this case we also use a defined component type `image`
            content: { type: 'image' },
            // This triggers `active` event on dropped components and the `image`
            // reacts by opening the AssetManager
            activate: true,
          }
        ]
      },
      layerManager: {
        appendTo: '.layers-container'
      },
    });
    editor.Panels.addPanel({
      id: 'panel-top',
      el: '.panel__top',
    });
    editor.Panels.addPanel({
      id: 'basic-actions',
      el: '.panel__basic-actions',
      buttons: [
        {
          id: 'visibility',
          active: true, // active by default
          className: 'btn-toggle-borders',
          label: '<u>B</u>',
          command: 'sw-visibility', // Built-in command
        }, {
          id: 'export',
          className: 'btn-open-export',
          label: 'Exp',
          command: 'export-template',
          context: 'export-template', // For grouping context of buttons from the same panel
        }, {
          id: 'show-json',
          className: 'btn-show-json',
          label: 'JSON',
          context: 'show-json',
          command(editor) {
            editor.Modal.setTitle('Components JSON')
              .setContent(`<textarea style="width:100%; height: 250px;">
                ${JSON.stringify(editor.getComponents())}
              </textarea>`)
              .open();
          },
        }
      ],
    });
    editor.on('run:export-template:before', opts => {
      console.log('Before the command run');
      opts.abort = 0; // 0 = true 1 = false
    });
    editor.on('run:export-template', () => console.log('After the command run'));
    editor.on('abort:export-template', () => console.log('Command aborted'));
  }
}
</script>

<style>
#gjs {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
  border: 3px solid #444;
}

/* Reset some default styling */
.gjs-cv-canvas {
  top: 0;
  width: 100%;
  height: 100%;
}

.gjs-block {
  width: auto;
  height: auto;
  min-height: auto;
}

.panel__top {
  padding: 0;
  width: 100%;
  display: flex;
  position: initial;
  justify-content: center;
  justify-content: space-between;
}

.panel__basic-actions {
  position: initial;
}

.editor-row {
  display: flex;
  justify-content: flex-start;
  align-items: stretch;
  flex-wrap: nowrap;
  height: 300px;
}

.editor-canvas {
  flex-grow: 1;
}

.panel__right {
  flex-basis: 230px;
  position: relative;
  overflow-y: auto;
}
</style>

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.