Skip to content

Commit 6d0d3b1

Browse files
authored
fix(data-table): handle dynamic headers gracefully (#2195)
Fixes #2193
1 parent f258548 commit 6d0d3b1

File tree

2 files changed

+94
-7
lines changed

2 files changed

+94
-7
lines changed

src/DataTable/DataTable.svelte

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -263,12 +263,13 @@
263263
expanded = expandedRowIds.length === expandableRowIds.length;
264264
}
265265
$: if (radio || batchSelection) selectable = true;
266-
$: headerKeys = headers.map(({ key }) => key);
267266
$: tableCellsByRowId = rows.reduce((rows, row) => {
268-
rows[row.id] = headerKeys.map((key, index) => ({
269-
key,
270-
value: resolvePath(row, key),
271-
display: headers[index].display,
267+
rows[row.id] = headers.map((header, index) => ({
268+
key: header.key || `key-${index}`,
269+
value: header.key ? resolvePath(row, header.key) : undefined,
270+
display: header.display,
271+
empty: header.empty,
272+
columnMenu: header.columnMenu,
272273
}));
273274
return rows;
274275
}, {});
@@ -557,8 +558,8 @@
557558
</td>
558559
{/if}
559560
{#each tableCellsByRowId[row.id] as cell, j (cell.key)}
560-
{#if headers[j].empty}
561-
<td class:bx--table-column-menu={headers[j].columnMenu}>
561+
{#if cell.empty}
562+
<td class:bx--table-column-menu={cell.columnMenu}>
562563
<slot name="cell" {row} {cell} rowIndex={i} cellIndex={j}>
563564
{cell.display ? cell.display(cell.value, row) : cell.value}
564565
</slot>

tests/DataTable/DataTable.test.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,4 +772,90 @@ describe("DataTable", () => {
772772
expect.any(Object),
773773
);
774774
});
775+
776+
it("should handle changing number of headers without crashing", async () => {
777+
const rows = [
778+
{
779+
id: "a",
780+
name: "Load Balancer 3",
781+
protocol: "HTTP",
782+
port: 3000,
783+
rule: "Round robin",
784+
},
785+
{
786+
id: "b",
787+
name: "Load Balancer 1",
788+
protocol: "HTTP",
789+
port: 443,
790+
rule: "Round robin",
791+
},
792+
];
793+
794+
const headers5 = [
795+
{ key: "name", value: "Name" },
796+
{ key: "protocol", value: "Protocol" },
797+
{ key: "port", value: "Port" },
798+
{ key: "rule", value: "Rule" },
799+
{ key: "actions", value: "Actions" },
800+
];
801+
802+
const headers3 = [
803+
{ key: "name", value: "Name" },
804+
{ key: "protocol", value: "Protocol" },
805+
{ key: "port", value: "Port" },
806+
];
807+
808+
const { component, rerender } = render(DataTable, {
809+
props: {
810+
rows,
811+
headers: headers5,
812+
},
813+
});
814+
815+
// First render with 5 headers
816+
expect(component).toBeTruthy();
817+
818+
// Change to 3 headers - this should not crash
819+
await rerender({
820+
rows,
821+
headers: headers3,
822+
});
823+
824+
expect(component).toBeTruthy();
825+
826+
// Change back to 5 headers - this should not crash
827+
await rerender({
828+
rows,
829+
headers: headers5,
830+
});
831+
832+
expect(component).toBeTruthy();
833+
});
834+
835+
it("should handle empty headers correctly", async () => {
836+
const rows = [
837+
{
838+
id: "a",
839+
name: "Load Balancer 3",
840+
protocol: "HTTP",
841+
port: 3000,
842+
rule: "Round robin",
843+
},
844+
];
845+
846+
const headersWithEmpty = [
847+
{ key: "name", value: "Name" },
848+
{ key: "protocol", value: "Protocol" },
849+
{ key: "actions", value: "", empty: true, columnMenu: true },
850+
];
851+
852+
const { component } = render(DataTable, {
853+
props: {
854+
rows,
855+
headers: headersWithEmpty,
856+
},
857+
});
858+
859+
expect(component).toBeTruthy();
860+
});
775861
});

0 commit comments

Comments
 (0)