[QUESTION]: How to set editor html contents from custom component?
Question
I'm having trouble getting a custom block+component to display its template HTML inside the grapes editor. Within the exported HTML, the markup and CSS is generated as expected.
Within the editor though, the block doesn't leave behind any sort of UI (though it is dragging in successfully based on the exported html/css)
My question is:
What is the proper way to have the 'toHtml' method output also apply to the editor iframe?
Based on similar examples I see elsewhere, it seems like in every other case it has to be generated from the block content property. However, for reasons I'm omitting here, I have to use the object format for the content in order to get the functionality provided by custom components
Code:
block
const bm = editor.BlockManager;
bm.add('flex-columns', {
label: '2 Columns',
content: {
type: 'columns'
},
});
component
export default (editor, config = {}) => {
const domc = editor.DomComponents;
const defaultType = domc.getType('default');
const defaultModel = defaultType.model;
const defaultView = defaultType.view;
domc.addType('columns', {
model: defaultType.model.extend({
defaults: Object.assign({}, defaultType.model.prototype.defaults, {
rowAttr: {
class: `row`,
},
colAttrMain: Object.assign({}, {
'data-gjs-draggable': `row`,
}, {
class: `cell-main`
}),
colAttrAside: Object.assign({}, {
'data-gjs-draggable': `row`,
}, {
class: `cell-main`
}),
styleRow: `
.row {
display: flex;
justify-content: flex-start;
align-items: stretch;
flex-wrap: nowrap;
padding: 10px;
}
.row:first-child {
padding-right: 20px;
}
@media (max-width: 768px) {
.row {
flex-wrap: wrap;
}
}
`,
styleClm: `
.cell-aside {
min-height: 75px;
flex: 1;
}
.cell-main {
min-height: 75px;
flex: 2;
}`,
template: '',
}),
attrsToString: function (attrs) {
const result = [];
for (let key in attrs) {
let value = attrs[key];
const toParse = value instanceof Array || value instanceof Object;
value = toParse ? JSON.stringify(value) : value;
result.push(`${key}=${toParse ? `'${value}'` : `"${value}"`}`);
}
return result.length ? ` ${result.join(' ')}` : '';
},
initialize(o, opt) {
defaultType.model.prototype.initialize.apply(this, arguments);
const attrsRow = this.attrsToString(this.attributes.rowAttr);
const attrsCellAside = this.attrsToString(this.attributes.colAttrAside);
const attrsCellMain = this.attrsToString(this.attributes.colAttrMain);
const styles =
`<style>
${this.attributes.styleRow}
${this.attributes.styleClm}
</style>`
this.attributes.template =
`<div ${attrsRow}>
<div ${attrsCellAside}><p>Aside</p></div>
<div ${attrsCellMain}><p>Main</p></div>
</div>` + styles;
},
toHTML: function () {
if (!this.view || !this.view.el) {
let html = document.createElement('div');
const customRenderedEl = this.generateHtml();
html.appendChild(customRenderedEl);
console.log('html is', html);
return html.innerHTML;
}
},
generateHtml(el = this.view.el) {
let generatedSection = el;
generatedSection.innerHTML = this.attributes.template;
return generatedSection;
},
},
{
isComponent(el) {
var result = '';
if (el.tagName == 'DIV') {
result = {
type: 'columns'
};
}
return result;
}
}
),
view: defaultType.view
})
}
Within the HTML, here is what is shown:
<div class="row">
<div class="cell">
<p>Column
</p>
</div>
<div class="cell">
<p>Column
</p>
</div>
</div>
, with nothing shown in the grapes editor iframe
Answers (3)
Well with this this.attributes.template = ... you do nothing to the view so it's just empty. You have to update the model so the view reacts to the change.
Eg.
// inside the Model
// use init instead of initialize, so you avoid `defaultType.model.prototype...`
init () {
// ...
// if the component has no children
if (!this.components().length) {
this.components(`<div ${attrsRow}>
<div ${attrsCellAside}><p>Aside</p></div>
<div ${attrsCellMain}><p>Main</p></div>
</div>${styles}`);
}
}
This custom component is an adaptation of https://github.com/artf/grapesjs-blocks-flexbox
This issue has been automatically closed because there has been no response to our request for more information from the original author. With only the information that is currently in the issue, we don't have enough information to take action. Please reach out if you have or find the answers we need so that we can investigate further.
Related Questions and Answers
Continue research with similar issue discussions.
Issue #1888
[Question] Add custom html inside canvas
Hi there, I'm using grapes to export a custom json with all the information i need, instead of HTML and CSS. For doing that I'm parsing the...
Issue #1493
[QUESTION] render() works on the first time but not on subsequent calls
Hello, I've created a custom component that shows images using background-image on a <div> instead of using an <img> element. It's mostly w...
Issue #2008
[Question]The canvas turns dark and unmodifiable on adding a large piece of custom html.
I used to add custom html with editor.addComponent(). It works well at most of the time, but when I try to insert a large piece of HTML whi...
Issue #1693
[BUG|/QUESTION] Strange characters (Â) within CSS/HTML preview; Elements are not deleted completely
BUGAre you using the latest release (older versions are NOT supported)?0.14.50Are you facing the bug with your local copy of GrapesJS or wi...
Paid Plugins That Match This Issue
Curated by issue keywords and label relevance to help you ship faster.
Loading paid plugin recommendations...
Browse Plugin Categories
Jump directly to plugin category pages on the marketplace.