GrapesJS - Editable components

by artur_arseniev

HTML

<script src="https://unpkg.com/grapesjs"></script>
<link rel="stylesheet" href="https://unpkg.com/grapesjs/dist/css/grapes.min.css">
<script src="https://unpkg.com/grapesjs-blocks-basic"></script>
<div id="gjs">
  <div class="header">
    <h1>I'm a header placeholder</h1>
  </div>
  <div class="body" style="padding: 25px">
      <div style="padding: 15px" data-gjs-type="editable">
        <div>Content here</div>
        <div>Content here</div>
        <div>Content here</div>
      </div>
  </div>
  <div class="footer">
    <h1>I'm a footer placeholder</h1>
  </div>
</div>

CSS

body, html {
  margin: 0;
  height: 100%;
}

Babel + JSX

const plhPlugin = editor => {
	const { Components } = editor;
  
  // Update the main wrapper
  Components.addType('wrapper', {
    model: {
      defaults: {
        selectable: false,
        highlightable: false,
        draggable: false,
        droppable: false,
        propagate: ['highlightable', 'selectable', 'draggable', 'droppable']
      },
      // Return always the content of editable content (defined below)
      toHTML(opts) {
        const editable = this.findType('editable')[0];
        return editable ? editable.toHTML(opts) : '';
      },
    },
    view: {
      onRender({ el }) {
        el.style.pointerEvents = 'none';
      }
    }
  });
  
  // Create the editable component
  Components.addType('editable', {
    model: {
      defaults: {
        removable: false,
        draggable: false,
        copyable: false,
        propagate: [],
      },
    },
    view: {
      onRender({ el }) {
        el.style.pointerEvents = 'all';
      }
    }
  });
	
  // Patch for getCss to return always the content
  // from editable component
  editor.getModel().getCss = () => {
    const wrapper = editor.getWrapper();
    const cmp = wrapper.findType('editable')[0];
    return cmp ? editor.CodeManager.getCode(cmp, 'css') : '';
  };
};

const editor = grapesjs.init({
	container: '#gjs',
  height: '100%',
  fromElement: true,
  storageManager: false,
  plugins: ['gjs-blocks-basic', plhPlugin],
  layerManager: {
  	root: '[data-gjs-type="editable"]',
  }
});