Hello. I want to dev some of feature to control the table.
There are many feature for table the other editor like add columns, rows, set color, reset column width for each cell...
I just have a dev plan to implementation on below..
bm.add('table-block', {
id: 'table',
label: 'Table',
category: 'Basic',
attributes: { class: 'fa fa-table' },
content: `
<table class="table table-striped table-bordered table-resizable">
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</table>
`,
});
this is a dummy table 3x3. each cell have a text component.

{
defaults: {
...Component.prototype.defaults,
type: 'cell',
tagName: 'td',
draggable: ['tr'],
toolbar: [
{
attributes: { class: "fa fa-arrows" },
command: "tlb-move"
},
{
attributes: { class: "fa fa-flag" },
command: "table-insert-row-above"
}
]
},
},
add a custom command to insert row above.
run(editor, sender, opts) {
var domComponents = editor.DomComponents;
domComponents.addComponent({
tagName: 'table',
removable: true, // Can't remove it
draggable: true, // Can't move it
copyable: true, // Disable copy/past
style: { background: 'red'},
attributes: { title: 'here' },
content: `<tr data-gjs-type="row" data-highlightable="1">
<td data-gjs-type="cell" data-highlightable="1" style="min-width: 100px;"><div data-gjs-type="text" data-highlightable="1"></div></td>
});
}

Anyone have a nice idea? I cannot find a awesome plugin.
Have a nice day.
content inside the component definition is for static text (eg. the content is used for editing with Rich Text Editor) so you can't select its element once added, instead you should use components: '<tr data-gjs-type="row" ...'table-insert-row-above could be:editor.Commands.add('table-insert-row-above', editor => {
const selected = editor.getSelected();
if (selected.is('cell')) {
const rowComponent = selected.parent();
const rowIndex = rowComponent.collection.indexOf(rowComponent);
const cells = rowComponent.components().length;
const rowContainer = rowComponent.parent();
rowContainer.components().add({
type: 'row',
components: [ ...Array(cells).keys() ].map(i => ({
type: 'cell',
content: 'New Cell',
}))
}, { at: rowIndex });
}
});
Thanks for your kindness answer.
Hey, @cnaa97 @artf please help me with adding columns command or duplicate column because using toolbar removes all default command.
@shubh9415 It seems necessary to update a toolbar after command execution, duplication or adding columns. I handled to add a component:select event listener.
editor.on('component:selected', m => {
const compType = m.get('type');
switch (compType) {
case 'cell':
m.set('toolbar', getCellToolbar(editor)); // set a toolbars
}
...
}
Hey, @cnaa97 thanks, that was really quick response. I am getting an error with getCellToolbar() as if it not a default function. Please help me with this below is my code .
const components = this._editor.DomComponents;
const text = components.getType('text');
components.addType('cell', {
model: text.model.extend({
defaults: Object.assign({}, text.model.prototype.defaults, {
type: 'cell',
tagName: 'td',
draggable: ['tr'],
toolbar: [
{
attributes: { class: "fa fa-arrows" },
command: "tlb-move"
},
{
attributes: { class: "fa fa-flag" },
command: "table-insert-row-above"
},
{
attributes:{class:"fa fa-clone"},
command:"duplicate_column"
}
]
}),
},
{
isComponent(el) {
let result;
const tag = el.tagName;
if (tag == 'TD' || tag == 'TH') {
result = {
type: 'cell',
tagName: tag.toLowerCase()
};
}
return result;
}
}),
view: text.view,
});
this._editor.Commands.add('table-insert-row-above', editor => {
const selected = editor.getSelected();
if (selected.is('cell')) {
const rowComponent = selected.parent();
const rowIndex = rowComponent.collection.indexOf(rowComponent);
const cells = rowComponent.components().length;
const rowContainer = rowComponent.parent();
rowContainer.components().add({
type: 'row',
components: [...Array(cells).keys()].map(i => ({
type: 'cell',
content: 'New Cell',
}))
}, { at: rowIndex });
}
});
I thought I could add a custom command to add columns also.
@shubh9415 Opps! getCellToolbar is my custom function.
In your code, you can use like this...
const TOOLBAR_CELL = [
{
attributes: { class: "fa fa-arrows" },
command: "tlb-move"
},
{
attributes: { class: "fa fa-flag" },
command: "table-insert-row-above"
},
{
attributes:{class:"fa fa-clone"},
command:"duplicate_column"
}
];
const getCellToolbar = () => TOOLBAR_CELL;
this._editor.on('component:selected', m => {
const compType = m.get('type');
switch (compType) {
case 'cell':
m.set('toolbar', getCellToolbar()); // set a toolbars
}
...
}
Hey, @cnaa97 thanks, that was my mistake but I wanted to know how we can duplicate column in the table. I was trying with the "duplicate_column" command but doesn't seem to work. Do you know any workaround?
Is there a way we can add additional icons in the toolbar. adding using a function also removes the default commands. If I don't add toolbar there is a duplicate icon in the table cells
Hey, @cnaa97 thanks, that was my mistake but I wanted to know how we can duplicate column in the table. I was trying with the "duplicate_column" command but doesn't seem to work. Do you know any workaround?
@shubh9415 How about this approach?
In duplicate_column command...
rowContainer
.components()
.add(
{ type: 'row', components: [...rowComponent.components().models.map((cell) => {
return {
type: cell.get('type'),
content: cell.get('content'),
}
})] },
{ at: rowIndex }
Hey, @cnaa97 thanks, the duplicate functionality is working but it is adding a tr and not td. Also, I know I would be asking for too much but if you anyhow have implemented delete function also? I just wanted to add extra functionality to the existing toolbar but that doesn't seem to be working right now. Please forgive me I just started using it.
Hey, @cnaa97 No worries I have added the default commands in the toolbar. I got what I wanted.
Thanks for helping.
Below is the code
const blockManager = this._editor.BlockManager;
blockManager.add('table-block', {
id: 'table',
label: 'Table',
category: 'Basic',
attributes: { class: 'fa fa-table' },
content: `
<table class="table table-bordered table-resizable">
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</table>
`,
});
const TOOLBAR_CELL = [
{
attributes: { class: "fa fa-arrows" },
command: "tlb-move"
},
{
attributes: { class: "fa fa-flag" },
command: "table-insert-row-above"
},
{
attributes: {class: 'fa fa-clone'},
command: 'tlb-clone',
},
{
attributes: {class: 'fa fa-trash-o'},
command: 'tlb-delete',
}
];
const getCellToolbar = () => TOOLBAR_CELL;
const components = this._editor.DomComponents;
const text = components.getType('text');
components.addType('cell', {
model: text.model.extend({
defaults: Object.assign({}, text.model.prototype.defaults, {
type: 'cell',
tagName: 'td',
draggable: ['tr'],
}),
},
{
isComponent(el) {
let result;
const tag = el.tagName;
if (tag == 'TD' || tag == 'TH') {
result = {
type: 'cell',
tagName: tag.toLowerCase()
};
}
return result;
}
}),
view: text.view,
});
this._editor.on('component:selected', m => {
const compType = m.get('type');
switch (compType) {
case 'cell':
m.set('toolbar', getCellToolbar()); // set a toolbars
}
});
this._editor.Commands.add('table-insert-row-above', editor => {
const selected = editor.getSelected();
if (selected.is('cell')) {
const rowComponent = selected.parent();
const rowIndex = rowComponent.collection.indexOf(rowComponent);
const cells = rowComponent.components().length;
const rowContainer = rowComponent.parent();
rowContainer.components().add({
type: 'row',
components: [...Array(cells).keys()].map(i => ({
type: 'cell',
content: 'New Cell',
}))
}, { at: rowIndex });
}
});
Most helpful comment
Hey, @cnaa97 No worries I have added the default commands in the toolbar. I got what I wanted.
Thanks for helping.
Below is the code