Issue #2043💬 AnsweredOpened May 28, 2019by megarg0 reactions

Adding custom component does not work

快速解答by artf

First of all, use the improved API. The isComponent is triggered only if you need to parse an HTML string, if you pass the component object (eg. { type: 'input2', }) the parsing is not necessary. You don't see anything in the canvas because obviously there is no INPUT2 element in HTML5

Read full answer below ↓

Question

I have done a lot of research but still could not add a custom component. I tried the example in official docs (to modify behavior of "input" element and it is working fine). https://grapesjs.com/docs/modules/Components.html#define-new-component

But the above example is for modifying existing component ("input").

I am trying to figure out how to create a new component. Following is my code, but it is not working (I am not printing anything in console when I drag it in the form). - note that I used the official example and changed it a bit to create this custom component.

Please help on what I may be doing wrong here...

  comps.addType('input2', {
      // Define the Model
      model: defaultModel.extend({
        // Extend default properties
        defaults: Object.assign({}, defaultModel.prototype.defaults, {
          // Can be dropped only inside `form` elements
          draggable: 'form, form *',
          // Can't drop other elements inside it
          droppable: false,
代码片段TEXT
// Traits (Settings)
            
            }),
          },
          // The second argument of .extend are static methods and we'll put inside our
          // isComponent() method. As you're putting a new Component type on top of the stack,
          // not declaring isComponent() might probably break stuff, especially if you extend
          // the default one.
          {
            isComponent: function(el) {
              if(el.tagName == 'INPUT2'){
                console.log('I am at isComponent: el:', el);
                return {type: 'input2'};
              }
            },
          }),

          // Define the View
          view: defaultType.view.extend({
          // Bind events
          events: {
            // If you want to bind the event to children elements
            // 'click .someChildrenClass': 'methodName',
            click: 'handleClick',
            dblclick: function(){
              alert('Hi!');
            }
          },

          // It doesn't make too much sense this method inside the component
          // but it's ok as an example
          randomHex: function() {
            return '#' + Math.floor(Math.random()*16777216).toString(16);
          },

          handleClick: function(e) {
            this.model.set('style', {color: this.randomHex()}); // <- Affects the final HTML code
            this.el.style.backgroundColor = this.randomHex(); // <- Doesn't affect the final HTML code
            // Tip: updating the model will reflect the changes to the view, so, in this case,
            // if you put the model change after the DOM one this will override the backgroundColor
            // change made before
          },

          // The render() should return 'this'
          render: function () {
            // Extend the original render method
            defaultType.view.prototype.render.apply(this, arguments);
            this.el.placeholder = 'My Text here'; // <- Doesn't affect the final HTML code
            return this;
          },
        }),
      });


       // A block for the custom component
       editor.BlockManager.add('input2', {
          label: 'My custom component',
          attributes: {
            class:'input2'
          },
          content: {
            // Built-in 'map' component
            type: 'input2',
            tagName: 'INPUT2',
           // style: { height: '350px'},
            // Once inserted it can't be removed (just an example)
            removable: false
          }
        
        //content: (<div>Foo</div>),
      });

Answers (1)

artfMay 30, 2019

First of all, use the improved API. The isComponent is triggered only if you need to parse an HTML string, if you pass the component object (eg. { type: 'input2', }) the parsing is not necessary.

You don't see anything in the canvas because obviously there is no INPUT2 element in HTML5

Related Questions and Answers

Continue research with similar issue discussions.

Paid Plugins That Match This Issue

Curated by issue keywords and label relevance to help you ship faster.

View all plugins

Loading paid plugin recommendations...

Free option

Check the open-source GrapesJS plugins on GitHub or run a quick search in our free catalog.

Browse free plugins →
Premium option

Premium plugins ship with support, regular updates, and production-ready features — save days of integration work.

Browse premium plugins →

Browse Plugin Categories

Jump directly to plugin category pages on the marketplace.