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

[Questions] Enrich any component with the serverside if or foreach expressions (namely, MVEL) #2801

Closed fedd closed 4 years ago

fedd commented 4 years ago

I am researching how to make a template with server side expressions that will repeat a component (foreach) or completely remove it (if). My backend parses templates with mvel.

What I am thinking is to add a couple of settings to all or some select elements. For example, to a <div> of a Cell, so it looks like this:

<div mvel-foreach="item : people" class="cell" id="iuck">
    ....some content dropped inside...@{item.lastName}... ...etc etc
</div>

Or to a Text (mvel-ending inserts separator between items):

<div mvel-ending="', '" mvel-foreach="item : people" id="iohm">@{item.lastName}</div>

After that I am planning to hack a postprocessor that will surround the repeating elements with actual mvel expressions:

@foreach{item : people}<div id="iohm">@{item.lastName}</div>@end{', '}

My dirty postprocessor will be responsible for the reverse replacement of expressions with tag attributes before loading the template into the GrapesJs editor with setComponents method.

So the question N1 is what I am missing, is there a better way to surround some select (or all) elements with server side expressions that are not actually tags?

Question N2 is how do I actually add those settings to all or some elements. I was reading the docs and decided that if I update the root component type called "default", I will add my 3 fields to all of the elements editors, so I've done this:

    var editor = grapesjs.init({
        height: '100%',
        container: editorDiv,
        showOffsets: true,
        fromElement: false,
        noticeOnUnload: false,
        storageManager: false,
        plugins: ['gjs-preset-webpage'],
        canvas: {
            styles: [
                'w3.css'
            ]
        }
    });

    const mvelModel = {
        model: {
            defaults: {
                traits: [
                    'mvel-if',
                    'mvel-foreach',
                    'mvel-ending',
                ]
            }
        }
    };

    editor.DomComponents.addType('default', mvelModel);

This turned out to be wrong: only the Cells in Columns in the Basic set of Blocks got updated, and my fields replaced the standard setting fields instead of being merged, so I am obviously missing how the component types extend each other and how do I merge my traits into the components.

Ju99ernaut commented 4 years ago

To surround an element take look at toHtml, you can search it in the issues for examples.

In any case I don't think it's a good idea to replace the default component type, I'd suggest creating a new component that extends the default type and using isComponent to determine how it is assigned. The docs for components might be helpful

fedd commented 4 years ago

The docs for components might be helpful

I've written my code based on this article. It says,

Updating component types is quite easy, let's see how: .... // The defaults property is handled differently // and will be merged with the old defaults

So I am updating, not the default, but a simple "input" component type now with this:

    const mvelModel = {
        model: {
            defaults: {
                traits: [
                    'mvel-if',
                    'mvel-foreach',
                    'mvel-ending',
                ]
            }
        }
    };
    editor.DomComponents.addType('input', mvelModel);

Still, instead of merging the new traits, it replaces the previously defined traits for the input with the new ones.

Any idea how to add setting items to an existing component type? Or at least how to retrieve the existing traits? Updating the component types will satisfy my needs without extending all of them and duplicating the number of those types

artf commented 4 years ago

@fedd you can add your new traits in model.init function