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

Custom Component Integration #2154

Closed adelliinaa closed 2 years ago

adelliinaa commented 5 years ago

Hello!

I want to integrate a custom component with GrapesJS, using Angular CLI 7, but it doesn’t render. My component is built on top of another open-source component. When I want to include it in any Angular project, I would just import the dependencies/libraries in the typescript files and the component itself (e.g.:

) in the HTML.

In order to use it within GrapesJS, I initially created a Block Manager, where I attached my custom component:

var editor = grapesjs.init({...}); var blockManager = editor.BlockManager;

blockManager.add(‘custom-comp’, { label: ‘Custom block', content: '

', });

But this approach seem to work only for GrapesJS components, so I tried to follow this implementation https://github.com/artf/grapesjs-mjml .

Would it suffice if I use only: var type = ‘custom-comp’; blockManager.addType(type, { isComponent(el) { if(el.tagName == type.toUpperCase()) {return {type, content:el.innerHTML} } } }). I don’t quite understand whether model() and view() are compulsory to define and their usage. Would my component still render without including these? (like it is suggested here: https://github.com/artf/grapesjs-mjml/blob/master/src/components/Text.js)

artf commented 5 years ago

@adelliinaa let's start from a simple question because I don't understand, what kind of editor are you trying to create? A builder for Angular components?!?

adelliinaa commented 5 years ago

I want to create a form builder similar to the one which you created with the MJML components, but using Angular CLI instead of JS. And yes, the customed components which I want to integrate within GrapesJS are built in Angular as well.

adelliinaa commented 5 years ago

@artf yes, I want to integrate Angular 7 components - which are built with HTML, CSS and Typescript

artf commented 5 years ago

Ok, but what will you do with the output (Angular components) of the editor? I mean, how you will use it at the end? Anyway, I see two different approaches to this kind of situation:

  1. Create a custom render for each component (the exact thing/concept I've made with MJML). This is the most accurate approach because I should see in the canvas the exact component of the framework (eg. obviously if the renderer uses the same "compiler", in your case the Angular framework). Probably not the easiest approach as you have to grasp a good knowledge about both frameworks (eg. in your case Angular and GrapesJS) but for sure the best in the long term, once the renderer is implemented new components could be integrated without any hassle

  2. You can create a kind of placeholder component, when the result will be always an HTML of your Angular components but the view is totally up to you to build. Example:

    editor.DomComponents.addType('InputGroup', {
    model: {
        defaults: {
            // The tag name that will be used in the final code
            tagName: 'InputGroup',
            attributes: { customProp: 'val1' },
            // You would use traits to customize custom properties
            traits: [
                {
                    type: 'select',
                    name: 'customProp',
                    options: [
                        { value: 'val1', name: 'Value 1' },
                        { value: 'val2', name: 'Value 2' },
                    ]
                }
            ]
        }
    },
    view: {
        // eg. You can customize the tag in the canvas
        // By default, the view will use the same tag of the model
        tagName: 'div',
        onRender() {
            // What the user see in the canvas is totally up to you
            // it can be a simple image as a placeholder or
            // you can make it as much close to the original markup
            const attrs = this.model.getAttributes();
            this.el.innerHTML = `<div>
                My custom HTML for this component<br>
                My custom prop: ${attrs['customProp']}
            </div>`;
        }
    }
    });

    This is the easiest but as you can see you have to setup a new view for each component.