Issue #1661💬 AnsweredOpened December 14, 2018by Konger19680 reactions

I've created html table and cannot drag new elements to table cells

快速解答by artf

Hi Konstantin, by doing this this.el.innerHTML = template; you're basically removing components by replacing them with a static HTML. Each component, once inserted inside the canvas has a Model (let's say, the component's JSON structure) bind to its View (render elements), so this View.el.innerHTML = '<div>...</div>'...

Read full answer below ↓

Question

Hello. if I create html table with next block of code, everything works, I'm able to drop a Quote, for example, to any cell:

 bm.add('table1centered', {
        label: '1 centered',
        category: 'Button Layout',
        attributes: { class: 'fa fa-table' },
        content: '<f7-list-item iPatrolType="f7-table">
        <table border="0" width="100%" style="min-height:5mm;">
          <tbody>
            <tr>
              <td width="45%">
              </td>
              <td width="10%">
              </td>
              <td width="45%">
              </td>
            </tr>
          </tbody>
        </table>
        </f7-list-item>'
    });

But next code produces html table with no possibility to drop new element into a cell. What am I doing wrong?

   bm.add('f7-list-item-table', {
        label: 'Table',
        category: 'Button Layout',
        attributes: { class: 'fa fa-table' },
        content: '<f7-list-item iPatrolType="f7-table"></f7-list-item>'
    });
    domComps.addType('f7-list-item-table', {
        model: dModel.extend({
            defaults: Object.assign({}, dModel.prototype.defaults,
                {
                    traits: [
                        //         // strings are automatically converted to text types
                        { type: 'number', label: 'columns', name: 'columns', placeholder: 'eg. columns quantity', default: 3 },
                        { type: 'text', label: 'column widths', name: 'columnwidths', placeholder: 'eg. 33%,34%,33%', default: '33%,34%,33%' },
                    ]
                }),
            initialize(o, opt) {
                dModel.prototype.initialize.apply(this, arguments);

                this.get('traits').each(function (trait) {
                    if (trait.get('name') == 'columns') {
                        trait.set('value', 3);
                    }
                    if (trait.get('name') == 'columnwidths') {
                        trait.set('value', '33%,34%,33%');
                    }
                });

            },
            showalert(mess) {
                setTimeout(() => { alert(mess); }, 1000);
            },
            getHtmlTemplate() {
                var columns = this.get('traits').where({ name: 'columns' })[0].get('value');
                var columnwidths = this.get('traits').where({ name: 'columnwidths' })[0].get('value');
                var columnwidthsArray = columnwidths.split(",");

                var template = '<f7-list-item iPatrolType="f7-table"><table width="100%" style="min-height:5mm;"><tr class="row">';
                // this.showalert(template);
                for (let index = 0; index < columns; index++) {
                    var wStr = columnwidthsArray.length >= index ? columnwidthsArray[index] : '';
                    if (wStr && !wStr.endsWith('%'))
                        wStr += '%';
                    template += '<td' + (wStr ? ' width="' + wStr + '"' : '') + ' class="cell"></td>';
                }
                template += '</tr></table></f7-list-item>';

                return template;
            },
            toHTML: function () {
                return this.getHtmlTemplate();
            }
        },
            {
                isComponent: function (el) {
                    if (el.tagName == 'F7-LIST-ITEM' && el.getAttribute('iPatrolType') == 'f7-table') {
                        return { type: 'f7-list-item-table' };
                    }
                },
            }),

        view: dView
            .extend({
                tagName: 'f7-list-item',
                initialize(o) {
                    dView.prototype.initialize.apply(this, arguments);
                    this.listenTo(this.model,
                        'change:attributes:columns ' +
                        'change:attributes:columnwidths '
                        , this.render)
                },
                showalert(mess) {
                    setTimeout(() => { alert(mess); }, 1000);
                },
                getHtmlTemplate() {
                    // this.showalert("getHtmlTemplate");
                    var columns = this.model.get('traits').where({ name: 'columns' })[0].get('value');
                    var columnwidths = this.model.get('traits').where({ name: 'columnwidths' })[0].get('value');
                    var columnwidthsArray = columnwidths.split(",");

                    var template = `<li>
                    <table border="1" width="100%" style="min-height:15mm;"
                    >
                    <tr>`;
                    for (let index = 0; index < columns; index++) {
                        wStr = '';
                        var wStr = columnwidthsArray.length >= index ? columnwidthsArray[index] : '';
                        if (wStr && !wStr.endsWith('%'))
                            wStr += '%';
                        template += '<td ' + (wStr ? ' width="' + wStr + '"' : '') + ' ></td>';
                    }
                    template += '</tr></table></li> ';

                    return template;
                },
                render(...args) {
                    this.updateAttributes();
                    this.updateClasses();

                    var template = this.getHtmlTemplate();
                    this.el.className = "f7-list-item-table";
                    this.el.innerHTML = template;
                    // this.showalert(this.el.outerHTML);
                    return this;
                }
            }),
    });

Answers (3)

artfDecember 20, 2018

Hi Konstantin, by doing this this.el.innerHTML = template; you're basically removing components by replacing them with a static HTML. Each component, once inserted inside the canvas has a Model (let's say, the component's JSON structure) bind to its View (render elements), so this View.el.innerHTML = '<div>...</div>' it' is like just adding another View but without the Model, the editor doesn't see elements without models. You need to update the model if you want to keep components live, so in your case, probably what you probably need is to move your view.getHtmlTemplate content inside the init of the model

domComps.addType('f7-list-item-table', {
        model: dModel.extend({
			...
			// use init instead of initialize, so you can skip 
			// calling the parent method dModel.prototype.initialize....
			init() {
				...
				// Check if the component is empty
				if (!this.components().length) {
					this.components(`<li>
                    <table border="1"... you content from view.getHtmlTemplate`)
				}
			}
Konger1968December 20, 2018

Thanks.

lock[bot]December 20, 2019

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.

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 →

Related tutorials

In-depth guides on the same topic.

All tutorials →

Browse Plugin Categories

Jump directly to plugin category pages on the marketplace.