Mimic customRTE behavior when parsing content
Now that I think through this a bit more, option 1 wouldn't really work for me since I want to prevent any inline styles from getting removed, as well as preventing any id's/classes/attributes from getting added to the child elements. So I guess that leaves option 2 or maybe another solution that I haven't thought of.
Read full answer below ↓Question
Hi @artf,
I'd like to replicate this behavior when calling editor.setComponents("<div>This is a text component. <span style='font-size: 20px;'>This is a nested element that I don't want get parsed out.</span></div>"). In that example, I would want the nested span to not get parsed as its own component so that I cannot select it or interact with it in any way (much the same as if I had enabled/disabled a customRTE on the div).
I'm seeing 2 options here:
- After calling
editor.setComponents, programmatically enable and disable RTE on outer div so that the child elements & text are treated ascontenton thediv. I'm pretty sure this would work without making any changes to grapesjs core...haven't tested it out just yet. - Modify the behavior of
ParseHtml.parseNodeto somehow identify that thedivshould not parse out its child elements/text. Maybe something like this using a a new property returned fromisComponent:
var defaultType = editor.DomComponents.getType("default");
editor.DomComponents.addType('some-custom-component-type', {
model: defaultType.model.extend(
{
},
{
isComponent: function(el) {
if(el.hasAttribute && el.hasAttribute("data-some-custom-component-type")){
return {
type: 'some-custom-component-type',
parseChildContent: false // new property that will tell the parser not to bother with parsing the children
};
}
}
}
),
view: defaultType.view
});
... // changes to ParseHtml.parseNode() below
if (nodeChild === 1 && firstChild.nodeType === 3) {
!model.type && (model.type = 'text');
model.content = firstChild.nodeValue;
} else if (model.hasOwnProperty("parseChildContent") && !model.parseChildContent) { // check for the new property to prevent the default node parsing behavior
model.content = node.innerHTML;
} else {
model.components = this.parseNode(node);
}
...
editor.setComponents("<div data-some-custom-component-type>This is a text component. <span style='font-size: 20px;'>This is a nested element that I don't want get parsed out.</span></div>")
Any thoughts on exploring option 2? Would you consider accepting a pull request that adds that new functionality to the parser? It wouldn't necessarily need to be driven by a custom component...I think a property like data-parse-child-content="false" could also be an option, or perhaps simply recognizing that a customRTE is being used and just check for model.type === "text" instead of parseChildContent.
My use case for this is that I'm going to be using a customRTE, but there's a good chance that the content that initially gets set into the editor will have a lot of nested text components which I'd like to treat as a single component.
Answers (3)
Now that I think through this a bit more, option 1 wouldn't really work for me since I want to prevent any inline styles from getting removed, as well as preventing any id's/classes/attributes from getting added to the child elements. So I guess that leaves option 2 or maybe another solution that I haven't thought of.
Hey Ryan what about this custom component
const domc = editor.DomComponents;
const textType = domc.getType('text');
domc.addType('raw-text', {
model: textType.model.extend({
},{
isComponent: function(el) {
if (el.hasAttribute && el.hasAttribute('data-raw-text')) {
return {
type: 'raw-text',
content: el.innerHTML,
components: [] // this will avoid parsing children
};
}
}
}
),
view: textType.view.extend({
disableEditing() {
const model = this.model;
const rte = this.rte;
if (rte && model.get('editable')) {
rte.disable(this, this.activeRte);
model.set('content', this.getChildrenContainer().innerHTML)
.trigger('change:content', model);
}
this.rteEnabled = 0;
this.toggleEvents();
},
})
});
Thanks @artf! I bet your suggestion will work for me - I'll test it out in the next few hours.
Related Questions and Answers
Continue research with similar issue discussions.
Issue #792
Script property using function don't work with blocks
In Components & JS docs there's this example: This works perfectly. But I couldn't use a function instead of a string in script, as is said...
Issue #1421
[Bug]: "disabled" instead of "active" class for Panel Button View
Hello I assume there is a bug with class when Panel Button is disabled https://github.com/artf/grapesjs/blob/dev/src/panels/view/ButtonView...
Issue #1846
[Question]: Using ngModel on component that contains groups of tagName
I have tried this solution https://github.com/artf/grapesjs/issues/1819#event-2158016066 But on custom components Let's say, i have a mixtu...
Issue #1688
on set model content property image and text written in content is not editable in grapejs canvas.
WARNING READ and FOLLOW next 5 steps, then REMOVE them before posting the issueFollow CONTRIBUTING Guidelines https://github.com/artf/grape...
Paid Plugins That Match This Issue
Curated by issue keywords and label relevance to help you ship faster.
Loading paid plugin recommendations...
Check the open-source GrapesJS plugins on GitHub or run a quick search in our free catalog.
Browse free plugins →Premium plugins ship with support, regular updates, and production-ready features — save days of integration work.
Browse premium plugins →Related tutorials
In-depth guides on the same topic.
Browse Plugin Categories
Jump directly to plugin category pages on the marketplace.