Grapesjs: [QUESTIONS] Custom Component disappear on Save (Vue.js)

Created on 31 Mar 2020  路  9Comments  路  Source: artf/grapesjs

Hi All,

I'm trying to test adding some custom Vue.js components to the block manager, and at first appearance, all is well - it renders correctly and vue components are responsive.

But if I save the template, and reload my page, and supply the storageManager with 'gjs-style', 'gjs-components', 'gjs-html', 'gjs-css'.

The custom component no longer renders. It appears the the storageManager removes any script tags???? As if I check my REST GET request, 'gjs-html' does contain the

All 9 comments

Hi @adamwpe !

Script tag importing is disabled by the default editor configuration, which explains why your scripts tags are stripped out by the HTML Parser, setting the allowScripts editor configuration option to true should solve the issue, eg:

grapesjs.init({
    // [...]
    allowScripts: true,
    // [...]
});

Hope this helps :)

Hi @mcottret

Thanks for the reply, but it was already set to true, forgot about that variable :(

This is my example init:

// Initialise the editor
var editor = grapesjs.init({
    height: '100%',
    noticeOnUnload: 1,
    allowScripts: true,
    container : '#gjs',
    avoidInlineStyle: true,
    fromElement: true,
    jsInHtml: true,
    plugins: ['gjs-preset-webpage'],
    storageManager: {
        type: 'remote',
        id: 'gjs-',
        autosave: true,
        autoload: true,
        storeComponents: true,
        contentTypeJson: true,
        stepsBeforeSave: 1,
        urlStore: '', 
        urlLoad: '/stores/get_store_page_data?store_page_data_id=<?php echo $id; ?>'
    },
    canvas: {
        scripts: ['https://cdn.jsdelivr.net/npm/vue/dist/vue.js'],
        styles: ['/../../../assets/css/main.css',
                 '/../../../assets/css/default.css',
                 'https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css'],
    },
    assetManager: {
        upload: '/clients/post_upload_gallery_image',
        uploadName: 'attachment',
        autoAdd: 1,
        dropzone: 0,
        params: {
              token: '<?php echo $this->security->get_csrf_hash() ?>'
        },
        assets: []
    },
    styleManager: {
        clearProperties: true,
    },
    pluginsOpts: {
        'gjs-preset-webpage': {
            formsOpts: false,
            countdownOpts: false,
            textExtra: 'Rotation',
            textTypography: 'Content'
        }
    }
});

Interestingly, If I change the component script from an object to a string:

image

It works!?!

Instead of:

image

Is that expected behavior? If so, what's the workaround (Apart from keeping it a string :))?

Thanks again for the reply 馃憤

I don't know, according to the docs both approaches should be valid so that might be a bug. I'll try looking into it, unless someone finds an answer in the meantime.

Cheers !

@adamwpe i believe you are not using the latest version!

Hi @pouyamiralayi

I'm using V 0.16.3:

https://cdnjs.cloudflare.com/ajax/libs/grapesjs/0.16.3/grapes.min.js

Thanks

The script property is not stored in the JSON, so you have to create a custom component. I know that this is how is indicated in docs, but I'd never found time to update it 馃槥

@artf Sorry, not too sure what you mean that it's stored in the JSON. What do I need to do differently?

Do I need to append the canvas like this?

// Append components directly to the canvas
editor.addComponents(`<div>
  <img src="https://path/image" />
  <span title="foo">Hello world!!!</span>
</div>`);

```` 

or something like this (If so, where do I put the content?):

editor.DomComponents.addType('vue_test', {
model: dModel.extend({
init() {
this.listenTo(this, 'change:attributes', this.reRender);
},
removed() {

            },
            defaults: Object.assign({}, dModel.prototype.defaults, {
                removable: true,
                draggable: true,
                droppable: true,
                badgable: true,
                stylable: true,
                highlightable: true,
                copyable: false,
                resizable: false,
                editable: false,
                hoverable: true
            }),
            reRender() {
                this.view.render();
            }
        }, {
            isComponent: function(el) {

                if(el.tagName === 'vue_test')
                    return {type: 'vue_test'};
            }
        }),
        view: dView.extend({

            events: {

            }
        })
    });

```

@adamwpe we had something like this in the past i apologize for not seeing it through!
go like this:

editor.DomComponents.addType('your-type', {
    model:{
        isComponent: el => {},
        defaults:{
            script:function(){},
        },
    }
})

there is no need to extend from dView & dModel in the latest versions.
and for the vue js integration please notice that the internal structure of your vue component would not be detected by grapesjs because there is no model generated for it! if you had any chance to overcome this scenario please let us know!
Cheers!

@pouyamiralayi

Thanks for that, pointed me in the right direction - so he is an example that works for me for rending a Vue Component and it will load back in :), but sure may be useful for someone else:

     editor.DomComponents.addType('vue_example', {
            model: {
                init() {

                    if (typeof this.getAttributes()['custom_att'] === "undefined")
                        this.addAttributes({'custom_att': 'default'});

                    // Onload, get the latest links
                    if (this.getTrait('custom_att') === undefined)
                        this.getTrait('custom_att').set('default');

                    this.getTrait('custom_att').set('default');

                    this.listenTo(this, 'change:attributes', this.reRender);

                },
                removed() {

                },
                defaults: {
                    removable: true,
                    draggable: true,
                    droppable: true,
                    badgable: true,
                    stylable: true,
                    highlightable: true,
                    copyable: false,
                    resizable: false,
                    editable: false,
                    hoverable: true,
                    traits: [
                        {
                            type: 'text',
                            label: 'Nice',
                            name: 'custom_att'
                        }
                    ],
                    script: function(){

                        const app1El = document.createElement("div");
                        app1El.id = 'app';

                        const app1Script = document.createElement("script");
                        app1Script.type = "text/javascript";
                        app1Script.src = "http://[::1]/assets/vue/vueApp.js";

                        this.appendChild(app1El);
                        this.appendChild(app1Script);

                    }
                },
                reRender() {
                    this.view.render();
                }
            },
            isComponent: function (el) {

                if (el.tagName === 'vue_example')
                    return {type: 'vue_example'};
            }

        });

        editor.BlockManager.add('vue_example', {
            id: 'vue_example',
            label: 'Vue Test',
            category: 'Vue',
            content: {
                tagName: 'vue_test',
                type: 'vue_example',
                editable: false
            }
        });

Thanks for the help everyone!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ionic666 picture ionic666  路  3Comments

crazyxhz picture crazyxhz  路  3Comments

mathiasbc picture mathiasbc  路  3Comments

faizansaiyed picture faizansaiyed  路  3Comments

kosirm picture kosirm  路  3Comments