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.37k stars 4.05k forks source link

Can it include widgets? #252

Closed Geczy closed 7 years ago

Geczy commented 7 years ago

Where I drag over a block, and instead of it displaying HTML, it displays a placeholder to the frontend.

Can this be done?

image

artf commented 7 years ago

@Geczy sure, you can create new component types, where in view you put whatever you want as a placeholder and in model, you might want override the toHTML and return some kind of variable to replace later

comps.addType('placeholder', {
  model: ...
        toHTML() {
          return '<div>VAR-TO-REPLACE</div>';
        }
        ...
  view: ...
      render() {
       this.el.innerHTML = 'placeholder content...';
       return this;
      }

  }),
});
Geczy commented 7 years ago

@artf What does the isComponent look like? Do I extend default type?

blockManager.add('placehole', {
  label: 'Orders Placeholder',
  category: 'Snippets',
  content: '<div class="my-block">This is a simple block</div>',
})

const defaultType = comps.getType('placehole')
comps.addType('placehole', {
  model: defaultType.model.extend({
    toHTML() {
      return '<div>{var-to-replace}</div>'
    },
  }),
  view: defaultType.view.extend({
    render(...args) {
      this.el.innerHTML = 'Image placeholder goes here' // <- Doesn't affect the final HTML code
      return this
    },
  }),
})

Is this correct?

How can I turn this into a block?

New to GrapesJS, trying to read the Wiki but still a little confusing

Geczy commented 7 years ago

Figured it out, for anyone else wondering it's like this:

blockManager.add('orderSnippet', {
  label: 'Orders',
  category: 'Snippets',
  content: { type: 'orderSnippet' },
})

const defaultType = comps.getType('default')
comps.addType('orderSnippet', {
  model: defaultType.model.extend({
    toHTML() {
      return '<div>{var-to-replace}</div>'
    },
  }),
  view: defaultType.view.extend({
    render(...args) {
      defaultType.view.prototype.render.apply(this, args)
      this.el.innerHTML = 'Image placeholder goes here' // <- Doesn't affect the final HTML code
      return this
    },
  }),
})
Geczy commented 7 years ago

So that works, but when I refresh it shows the <div>{var-to-replace}</div>

How can I make it show the placeholder again on refresh?

Geczy commented 7 years ago

Tried adding isComponent which is supposed to fix that I think, but that doesn't work

const editor = window.grapesjs.init({
  container: '#gjs',
  plugins: ['gjs-preset-newsletter', 'gjs-blocks-basic'],
})

editor.BlockManager.add('orderSnippet', {
  label: 'Order Items',
  category: 'Snippets',
  content: { type: 'orderSnippet' },
})

const defaultType = editor.DomComponents.getType('default')
editor.DomComponents.addType('orderSnippet', {
  model: defaultType.model.extend(
    {
      toHTML() {
        return '<div>{var-to-replace}</div>'
      },
    },
    {
      isComponent(el) {
        return { type: 'orderSnippet' }
      },
    }
  ),
  view: defaultType.view.extend({
    render(...args) {
      defaultType.view.prototype.render.apply(this, args)
      this.el.innerHTML = placeholderImage('Order Items')
      return this
    },
  }),
})

Can you see the issue? Even tried:

{
  isComponent(el) {
    return { type: 'orderSnippet' }
  },
}
Geczy commented 7 years ago

@artf

Refresh: image

What I want it to display on refresh, which it isn't currently:

image

Geczy commented 7 years ago

Solved via https://github.com/artf/grapesjs/issues/43

artf commented 7 years ago

@Geczy glad you've solved, but would like to point out that isComponent defined like this will break stuff in importing. isComponent is used by the editor to recognize HTML elements and attach the appropriate type. When you define a new Component Type, this one is added on top of the type stack and on any new HTML element, this stack is iterated from the top so with your isComponent everything will be of orderSnippet type.

Geczy commented 7 years ago

I was using that just to debug, I have it changed to https://github.com/artf/grapesjs/issues/260#issue-253742728

              isComponent(el) {
                if (
                  el &&
                  typeof el === 'object' &&
                  el.getAttribute &&
                  el.hasAttribute('data-type') &&
                  el.getAttribute('data-type') === camelCase(a.name)
                ) {
                  return { type: camelCase(a.name) }
                }
lock[bot] commented 5 years ago

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.