Use a passed HTMLTableCellElement as the cell directly

When a cell value is a <td>/<th>, append it to the row as-is instead of
wrapping it in a generated <td>, which would have produced invalid nested
cells. Any other HTMLElement still gets wrapped as before.
This commit is contained in:
CentreMetre
2026-06-15 21:15:34 +01:00
parent 436217a8ff
commit 95254027c4

View File

@@ -143,7 +143,8 @@ export abstract class Table<TRow extends object> {
* Creates a row, populated with data, for displaying in the table. * Creates a row, populated with data, for displaying in the table.
* @param data The data in the shape of `TRow`, with values populated. * @param data The data in the shape of `TRow`, with values populated.
* @return A HTMLTableRowElement that can then be set on a table. * @return A HTMLTableRowElement that can then be set on a table.
* @remarks If a cell value is an HTMLElement it is appended to the cell. A DOM node can only * @remarks If a cell value is an HTMLTableCellElement (a `<td>`/`<th>`) it is used as the cell
* directly; any other HTMLElement is appended inside a generated `<td>`. A DOM node can only
* exist in one place, so passing the same element instance to multiple rows moves it to the * exist in one place, so passing the same element instance to multiple rows moves it to the
* last row only. Pass a fresh element (or `el.cloneNode(true)`) per row. But keep in mind that * last row only. Pass a fresh element (or `el.cloneNode(true)`) per row. But keep in mind that
* el.cloneNode(true) does not keep event listeners, so if event listeners are used it is best * el.cloneNode(true) does not keep event listeners, so if event listeners are used it is best
@@ -153,14 +154,20 @@ export abstract class Table<TRow extends object> {
const row = document.createElement("tr"); const row = document.createElement("tr");
for (const column of this.columns) { for (const column of this.columns) {
const cell: HTMLTableCellElement = document.createElement("td");
const value = data[column.key] const value = data[column.key]
if (value instanceof HTMLTableCellElement) {
row.append(value); // already a cell, use it as-is
continue;
}
const cell: HTMLTableCellElement = document.createElement("td");
// Element values are inserted as children, not stringified. // Element values are inserted as children, not stringified.
if (value instanceof HTMLElement) { if (value instanceof HTMLElement) {
cell.appendChild(value); cell.appendChild(value);
row.append(cell); row.append(cell);
continue; // skip the textContent path that would wipe it continue; // skip the textContent path that would wipe it
} }
let cellValue = ""; let cellValue = "";