-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Resizable tables don't retain their column widths when the editor isn't editable #2041
Comments
Looking at this I am not entirely sure how the editor is rendering when See sandbox integrated with custom TableHead (from below): Custom TableHeader example: Add the style attribute and colwidth tweak (not sure it is necessary) addAttributes() {
return {
...this.parent(),
colwidth: {
default: null,
parseHTML: element => {
const colwidth = element.getAttribute('colwidth');
const value = colwidth
? colwidth.split(',').map(item => parseInt(item, 10))
: null;
return value;
},
},
style: {
default: null,
},
};
}, And renderHTML renderHTML({ HTMLAttributes }) {
let totalWidth = 0;
let fixedWidth = true;
if (HTMLAttributes.colwidth) {
HTMLAttributes.colwidth.forEach(col => {
if (!col) {
fixedWidth = false;
} else {
totalWidth += col;
}
});
} else {
fixedWidth = false;
}
if (fixedWidth && totalWidth > 0) {
HTMLAttributes.style = `width: ${totalWidth}px;`;
} else if (totalWidth && totalWidth > 0) {
HTMLAttributes.style = `min-width: ${totalWidth}px`;
} else {
HTMLAttributes.style = null;
}
return [
'th',
mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),
0,
];
}, Essentially the same needs to be done with TableCell as well. For also ensuring the Table is aligned, you can do a custom Table like the following: Add the style attribute addAttributes() {
return {
style: {
default: null,
},
};
}, And then custom renderHTML: renderHTML({ node, HTMLAttributes }) {
let totalWidth = 0;
let fixedWidth = true;
try {
// use first row to determine width of table;
const tr = node.content.content[0];
tr.content.content.forEach(td => {
if (td.attrs.colwidth) {
td.attrs.colwidth.forEach(col => {
if (!col) {
fixedWidth = false;
totalWidth += this.options.cellMinWidth;
} else {
totalWidth += col;
}
});
} else {
fixedWidth = false;
const colspan = td.attrs.colspan ? td.attrs.colspan : 1;
totalWidth += this.options.cellMinWidth * colspan;
}
});
} catch (error) {
fixedWidth = false;
}
if (fixedWidth && totalWidth > 0) {
HTMLAttributes.style = `width: ${totalWidth}px;`;
} else if (totalWidth && totalWidth > 0) {
HTMLAttributes.style = `min-width: ${totalWidth}px`;
} else {
HTMLAttributes.style = null;
}
return ['div', { class: 'table-wrapper' }, ['table', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), ['tbody', 0]]];
}, I've considered writing this up as a PR, but haven't spent enough time researching if each of the decisions in the above code are generic enough for general use. For example, I wrap each table with a |
Hi, actually.... I was struggling with the issue that I would like to have the width in % and not in px. I am still learning about tiptap and your example gave me a bit of an idea how this could be solved. Basically, you can loop in the renderHTML function over all trs and their respective tds and ths and set the "style" there. Also the idea of the aligned table is brilliant. |
For tables we use |
First of all, thank you for your contribution. Share one way to calculate the area value as a percentage in the table. const CustomTable = Table.extend({
addAttributes() {
return {
style: {
default: null,
},
};
},
renderHTML({ node, HTMLAttributes }) {
let totalWidth = 0;
let fixedWidth = true;
let _cols = [];
let _colSum = 0;
try {
const tr = node.content.content[0];
tr.content.content.forEach(td => {
let colwidth = 0;
if (td.attrs.colwidth) {
td.attrs.colwidth.forEach(col => {
if (!col) {
fixedWidth = false;
totalWidth += this.options.cellMinWidth;
} else {
totalWidth += col;
colwidth = col;
}
});
} else {
fixedWidth = false;
const colspan = td.attrs.colspan ? td.attrs.colspan : 1;
totalWidth += this.options.cellMinWidth * colspan;
}
_cols.push(colwidth)
_colSum = _colSum + colwidth;
});
} catch (error) {
fixedWidth = false;
}
const leftWidth = (totalWidth - _colSum);
const fixedRateAverage = totalWidth / _cols.length;
const zeroColLength = _cols.filter(x => x === 0).length;
const fluctuationAverage = leftWidth / (zeroColLength === 0 ? 1 : zeroColLength);
const zeroCol = Math.max(fixedRateAverage, fluctuationAverage);
_cols = _cols.map(x => ((x === 0 ? zeroCol : x) / totalWidth * 100).toFixed());
const noneCol = zeroColLength === _cols.length;
const ele = noneCol ? [] : _cols.map(x => ['col', mergeAttributes(this.options.HTMLAttributes, { style: `width: ${x}%;` })]);
if (noneCol) {
HTMLAttributes.style = null;
} else if (fixedWidth && totalWidth > 0) {
HTMLAttributes.style = `width: ${totalWidth}px; max-width: 100%;`;
} else if (totalWidth && totalWidth > 0) {
HTMLAttributes.style = `width: ${totalWidth}px; max-width: 100%;`;
} else {
HTMLAttributes.style = null;
}
return [
'div',
{ class: 'table-wrapper' },
[
'table',
mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),
['tbody', 0],
['colgroup', {}, ...ele]
]
];
},
}); If we complement the function at this point, |
Just let editable be true in the editor and set attributes border, pointerEvents, contenteditable and tabindex to make it unaccessable. At least it worked for me. |
If you have something like this ... CustomTable.configure({
cellMinWidth: 100,
resizable: true
}), the result is not as expected as the table will be not wrapped in a div on insert. |
Why is this issue closed? Why are the tables not retaining their styles when saves to HTML? I don't get it, really seems like a bug to me. Makes the resiable feature completely useless |
I did the following to get this to work in my package
Hope that may be helpful to some folks! I would contribute this upstream to tiptap, but I assume since CSS isn't bundled in general, it's not desirable to have the resizable column JS behavior for the editor on by default, requiring custom CSS to prevent resizing when If you install mui-tiptap, it bundles the default styles so it should "just work" when you use |
i used this as a quick fix: TableCell.extend({
renderHTML({ HTMLAttributes }) {
const attrs = mergeAttributes(this.options.HTMLAttributes, HTMLAttributes);
if (attrs.colwidth) {
attrs.style = `width: ${attrs.colwidth}px`;
}
return ['td', attrs, 0];
}
}) |
@philippkuehn Is there a reason the "quick fix" above can't be part of TableCell? It seams reasonable that if there's a |
@m3di thank you! it's really working and also |
What’s the bug you are facing?
I have an editable instance of the editor, which includes the table plugins. I have set the tables to be resizable. I resize my tables and save the content.
When I go to load that content into an editor that it not editable, the table columns lose the custom widths that I set.
How can we reproduce the bug on our side?
Create an instance of the editor which includes resizable tables.
Create a table and resize the columns.
Get the html from that editor
editor.getHTML()
and insert it as thecontent
for another editor that is not editable.The tables lose the custom widths that I set.
Can you provide a CodeSandbox?
https://codesandbox.io/s/unruffled-orla-fykjr?file=/src/App.vue
What did you expect to happen?
I expected the readonly version of the editor to still display the custom widths that I set, but for the columns to not be resizable.
Anything to add? (optional)
Thanks for your work on tiptap, its really awesome!
Did you update your dependencies?
Are you sponsoring us?
The text was updated successfully, but these errors were encountered: