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

global functions/variables #2181

Closed pouyamiralayi closed 5 years ago

pouyamiralayi commented 5 years ago

Hello there! recently i noticed this issue. I think it would be beneficial to have this feature. in contrast to the suggested approach by @artf that uses canvas scripts as a way to inject globally, i think this is not functional for the main purpose that this feature is intended for. in my opinion the main use case for having global variables and functions is the way script is handled inside the canvas: for each component type, it is executing a function every time that canvas is rendered. so if you are registering some sort of handlers for some events in your script, there is no way for you to manage those handlers(for instance detaching them from the event) because the execution context would be lost every time the canvas is rendered. so we need our handlers defined on the global scope. the common workaround for this is the idea that is used here i would be glad to hear from you @artf around this matter. thanks in advance.

artf commented 5 years ago

Sorry @pouyamiralayi but I believe you didn't get the total meaning of script property in Component (obviously you're not the only one, even if I try to explain this "script paradox" here)

What is asked in #1691 it just DOESN'T MAKE SENSE because the context in script property is like ANOTHER WORLD, the only way to communicate with those worlds is using interpolation strings (like explained in the documentation) and it's somehow similar to what the plugin you mentioned does.

Try to understand by taking the example from the mentioned issue and my comments.

/*
main-components.js
*/
// `temp` and `fnName`, being in the same context, probably 
// are required/used by the GrapesJS editor
var temp = {};
function fnName() {}

// ... here I create a component/block
bm.add("image-cropper", {
//...
    customProp: 'custom-value',
    // script property for the component/block
    script: function () {
        // Here I'm in another context
        // This part is might be the one stored in DB and then printed to 
        // the end user in some 'Home page'. 
        // Here, no one knows about GrapesJS editor, either `temp` or `fnName`
        console.log(temp, fnName); // are both undefined

        // The only way to "print" something from the model 
        // is to use interpolation
        console.log('{[ customProp ]}'); // will print 'custom-value'

        // But this works ONLY because before storing the string the 
        // editor replaces it with the property, so in DB it will store:
        console.log('custom-value');
    },

Is it clear right now?

pouyamiralayi commented 5 years ago

thanks for your kind answer @artf . after struggling with the idea i am reaching to the point that what you are saying is totally reasonable. that was very naive of me to bringing this matter up again sorry for that. the current workaround is completely correct and it's complement the canvas global scripts. and for those that are trying to implement a communication channel between global scripts and local ones, they can define an event bus globally and attach or detach listeners locally. the state is also saved using the interpolation of model values. Thanks in advance.

collindutter commented 3 years ago

@pouyamiralayi would you mind providing some more information on how you created a global event bus to send messages between global scripts and local ones? The editor embeds the grapesjs content in an iframe, so you can't use a global window object as an event bus.

Thanks!