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

How to get the external plugin CSS, JS and HTML through GrapesJS export feature? #2302

Closed Amitkumar85533 closed 5 years ago

Amitkumar85533 commented 5 years ago

I have used an external plugin javascript version of @fullCalendar into the GrapesJS. I am able to render the calendar on the canvas but I am unable to use GrapesJS export feature to get JS, CSS and HTML of the following.

I tried using
1) var html = editor.getHtml(); 2) var css = editor.getCss();
3) var js = editor.getJs(); 4) editor.on('component:mount', comp => console.log(comp.toHtml()));

Calendar rendered on Canvas -

Calender1

Export of GrapesJs Editor -

Calender2

Kindly help me! Thanks in advance ...

pouyamiralayi commented 5 years ago

Hi there! what you are looking for is using js inside components.

just include the required js and css in the canvas scripts and styles section:

canvas: {
            styles: [
                'https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/core/main.css',
                'https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/daygrid/main.css',
            ],
            scripts: [
                'https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/core/main.js',
                'https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/daygrid/main.js',
            ],
        },

after that build your own custom type component:

             model: {
                defaults: {
                    ccid:'',
                    tagName: 'div',
                    resizable:true,
                    script: function(){
                            const id = '{[ ccid ]}'
                            var calendarEl = document.getElementById(id);

                            var calendar = new FullCalendar.Calendar(calendarEl, {
                                plugins: [ 'dayGrid' ]
                            });
                            calendar.render();
                    }
                },
            },
            view:{
                init(){
                    this.model.set('ccid',this.model.ccid)
                }
            }

then on code preview you will see the result script:

image

cheers!

Amitkumar85533 commented 5 years ago

Hi @pouyamiralayi, Thanks for your help !!!! It is working. Now we are able to see the calendar on the export feature.

I was having a doubt, by the model.defaults and model.view I'm able to get the code in export but unable to render it on canvas. For rendering, I have used a render function in view. So is that the appropriate way or model.defaults and model.view are sufficient to render the calendar on the canvas.

Below I have shared my code snippet...

import { Calendar } from '@fullcalendar/core'; import dayGridPlugin from '@fullcalendar/daygrid'; import momentPlugin from '@fullcalendar/moment'; import moment from "moment";

export default (editor, config = {}) => { const domc = editor.DomComponents; const defaultType = domc.getType('link'); const defaultModel = defaultType.model; const defaultView = defaultType.view; const canvas = editor.canvas;

domc.addType('event-farm-calendar', {
    model:{
        defaults: {
            ccid:'',
            tagName: 'div',
            resizable:true,
            script: function(){
                    const id = '{[ccid]}';
                    var calendarEl = document.getElementById(id);
                    console.log('calendarEl => ',calendarEl)

                    var calendar = new FullCalendar.Calendar(calendarEl, {
                        plugins: [ dayGridPlugin ],
                        events: [
                            {
                            id: 'a',
                            title: 'my event',
                            start: '2019-09-20',
                            },
                            {
                            id:'b',
                            title: 'BCH237',
                            start: '2019-09-19T10:30:00',
                            end: '2019-09-19T11:30:00',
                            }
                        ],
                    });
                    calendar.render();
            }
        },
    },
    view:{
        init(){
            console.log("ccid => ",this.model.ccid);
            this.model.set('ccid',this.model.ccid)
        },
        onRender: function () {
            console.log("Calendar Component.js this.el => ", this.el)
            console.log("Inside Render Hello!")

            let calendar = new Calendar(this.el, {
                plugins: [dayGridPlugin, momentPlugin],
                defaultView: 'dayGridMonth',

                timeZone: 'UTC',
                events: [
                    {
                        id: 'a',
                        title: 'My Event 2',
                        start: '2019-09-20',
                        end: '2019-09-20'
                    },
                    {
                        id: 'b',
                        title: 'My Event 1',
                        start: '2019-09-21',
                        end: '2019-09-21'
                    }
                ],

                titleFormat: 'MMMM D, YYYY',

                eventClick: function (info) {
                    alert('Event: ' + info.event.title + '\n' + '\n' + 'Event Start:   ' + moment(info.event.start).format('MMMM Do YYYY'));

                    console.log("Event Clicked => ", info);

                }

            });

            setTimeout(function () {
                calendar.render();
            }, 500);

            return this;
        }
    }
})       

}

Kindly help me! Thanks in advance ...

pouyamiralayi commented 5 years ago

For rendering, I have used a render function in view.

if you want the editor to show users the calendar but not actually put it inside the final html, you must use view to render the calendar. more on this here.

So is that the appropriate way or model.defaults and model.view are sufficient to render the calendar on the canvas.

for your case, because you clearly stated:

I am unable to use GrapesJS export feature to get JS, CSS and HTML

going with the model is your case, because view does not put the calendar in the final html,JS code.

just notice on the code that you just posted, you have included the initialization code of calendar in both the view and in the script. this is redundant because you are forcing the view of your component to render what is already is rendered through script. cheers!

Amitkumar85533 commented 5 years ago

Thanks, @pouyamiralayi.

The MODEL render function is able to export in the final HTML. But we are unable to show users the calendar on the canvas after drag and drop with render function in MODEL that is why we used OnRender in the VIEW.

So, is the MODEL alone sufficient to render as well as add HTML to export feature? If yes could you please explain how?

Kindly help me! Thanks in advance ...

pouyamiralayi commented 5 years ago

. But we are unable to show users the calendar on the canvas after drag and drop with render function in MODEL that is why we used OnRender in the VIEW.

Did you try the component type definition i posted for you? it has been tested and it is working:

image

So, is the MODEL alone sufficient to render as well as add HTML to export feature? If yes could you please explain how?

yes. it will render the component in the canvas, and include the final code in final html.

if you need any further help for your specific case, i would appreciate a fiddle. cheers!

Amitkumar85533 commented 5 years ago

Thanks a lot, @pouyamiralayi. The code you gave was working. Our code was not able to pick the dom element to render the calendar. Now it is working as expected.

Thanks a lot for helping us out !!!! :-p

theSC0RP commented 3 years ago

Hi there! what you are looking for is using js inside components.

just include the required js and css in the canvas scripts and styles section:

canvas: {
            styles: [
                'https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/core/main.css',
                'https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/daygrid/main.css',
            ],
            scripts: [
                'https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/core/main.js',
                'https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/daygrid/main.js',
            ],
        },

after that build your own custom type component:

             model: {
                defaults: {
                    ccid:'',
                    tagName: 'div',
                    resizable:true,
                    script: function(){
                            const id = '{[ ccid ]}'
                            var calendarEl = document.getElementById(id);

                            var calendar = new FullCalendar.Calendar(calendarEl, {
                                plugins: [ 'dayGrid' ]
                            });
                            calendar.render();
                    }
                },
            },
            view:{
                init(){
                    this.model.set('ccid',this.model.ccid)
                }
            }

then on code preview you will see the result script:

image

cheers!

Hi @pouyamiralayi. If I want to add a stylesheet (like bootstrap), but not in grapesjs.init({...}), how should I do it? (Using editor object how can I add the styles and scripts?)

theSC0RP commented 3 years ago

Hi @pouyamiralayi. If I want to add a stylesheet (like bootstrap), but not in grapesjs.init({...}), how should I do it? (Using editor object how can I add the styles and scripts?)

I got answer to my question. Issue #3053