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.38k stars 4.05k forks source link

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

Closed joshk132 closed 3 years ago

joshk132 commented 3 years ago

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>
uchoaaa commented 3 years ago

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>
artf commented 3 years ago

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

joshk132 commented 3 years ago

@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>
artf commented 3 years ago

I think it might be an issue with your application. If you're able to create a reproducible demo please provide a link or we can't help you