GrapesJS Textable Component
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 style="padding: 25px">Hello World!!!</div>
</div>
CSS
body, html {
margin: 0;
height: 100%;
}
Babel + JSX
const newPlugin = (editor) => {
const newType = 'textable-cmp';
// Define a component with `textable` property
editor.Components.addType(newType, {
model: {
defaults: {
tagName: 'span',
textable: true,
placeholder: '{{ VARIABLE-1 }}',
},
getInnerHTML() {
return this.get('placeholder');
},
},
// The view below it's just an example for creating a different UX
view: {
events: {
'change': 'updatePlaceholder',
},
updatePlaceholder(ev) {
this.model.set({ placeholder: ev.target.value });
},
onAttrUpdate() {
const viewStyle = 'padding: 0px 5px 1px; border-radius: 3px; border: 1px solid #b300fd';
this.el.setAttribute('style', viewStyle);
},
onRender() {
const { model, el } = this;
const select = document.createElement('select');
const options = [ 'VARIABLE-1', 'VARIABLE-2', 'VARIABLE-3' ];
select.innerHTML = options.map(item =>
`<option value="{{ ${item} }}">${item}</option>`
).join('');
el.innerHTML = '';
el.appendChild(select);
select.setAttribute('style', 'padding: 0; border: none; appearance: none;');
select.value = model.get('placeholder');
},
}
});
editor.Blocks.add(newType, {
label: 'Textable component',
content: { type: newType },
select: true,
});
}
const editor = grapesjs.init({
container: '#gjs',
fromElement: 1,
height: '100%',
storageManager: { type: 0 },
plugins: ['gjs-blocks-basic', newPlugin]
});