diff --git a/packages/core/src/components/tree/test/tree.ct.ts b/packages/core/src/components/tree/test/tree.ct.ts index 9e1e09dcd92..1729486b947 100644 --- a/packages/core/src/components/tree/test/tree.ct.ts +++ b/packages/core/src/components/tree/test/tree.ct.ts @@ -463,3 +463,50 @@ regressionTest( await expect(items.nth(2)).not.toBeVisible(); } ); + +regressionTest( + 'should handle click events on custom rendered tree items', + async ({ mount, page }) => { + const tree = await initializeTree(mount, page); + + await tree.evaluate( + (t) => + ((t as HTMLIxTreeElement).renderItem = ( + _index, + item, + _dataList, + context, + update + ) => { + const el = document.createElement('ix-tree-item'); + const treeItem = item as TreeItem; + el.hasChildren = treeItem.hasChildren; + el.context = context[treeItem.id]; + + const container = document.createElement('div'); + container.classList.add('custom-content'); + container.style.display = 'flex'; + container.style.alignItems = 'center'; + + const name = document.createElement('span'); + name.innerText = treeItem.data.name; + + container.appendChild(name); + el.appendChild(container); + + update((updateTreeItem) => { + name.innerText = updateTreeItem.data.name; + }); + + return el; + }) + ); + + const root = tree.locator('ix-tree-item').first(); + await root.locator('.icon-toggle-container').click(); + + const customItem = tree.locator('ix-tree-item').nth(1); + await customItem.click(); + await expect(customItem).toHaveClass(/selected/); + } +); diff --git a/packages/core/src/components/tree/tree.tsx b/packages/core/src/components/tree/tree.tsx index 7e7f46450f6..3c56d9f6bf9 100644 --- a/packages/core/src/components/tree/tree.tsx +++ b/packages/core/src/components/tree/tree.tsx @@ -339,7 +339,16 @@ export class Tree { return; } - const id = target.getAttribute('data-tree-node-id'); + let treeNodeElement = target; + let id = treeNodeElement.dataset.treeNodeId; + + while (!id && treeNodeElement && treeNodeElement !== this.hostElement) { + treeNodeElement = treeNodeElement.parentElement as HTMLElement; + if (treeNodeElement) { + id = treeNodeElement.dataset.treeNodeId; + } + } + if (!id) { return; } @@ -361,7 +370,16 @@ export class Tree { return; } - const id = target.getAttribute('data-tree-node-id'); + let treeNodeElement = target; + let id = treeNodeElement.dataset.treeNodeId; + + while (!id && treeNodeElement && treeNodeElement !== this.hostElement) { + treeNodeElement = treeNodeElement.parentElement as HTMLElement; + if (treeNodeElement) { + id = treeNodeElement.dataset.treeNodeId; + } + } + if (!id) { return; } @@ -377,7 +395,9 @@ export class Tree { } if (!event.defaultPrevented) { - Object.values(this.context).forEach((c) => (c.isSelected = false)); + for (const c of Object.values(this.context)) { + c.isSelected = false; + } const context = this.getContext(id); context.isSelected = true; this.setContext(id, context);