From fe7aa0fccdd1057c780a52f33da7ee87921b8822 Mon Sep 17 00:00:00 2001 From: Emre AKA Date: Sat, 14 Dec 2024 19:00:27 +0300 Subject: [PATCH 1/2] fix(tree): added a watcher to recalculate selection keys when value to render changes to keep selection state up to date with rendered nodes. --- packages/primevue/src/tree/Tree.vue | 39 +++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/packages/primevue/src/tree/Tree.vue b/packages/primevue/src/tree/Tree.vue index db04745410..5070d7c160 100755 --- a/packages/primevue/src/tree/Tree.vue +++ b/packages/primevue/src/tree/Tree.vue @@ -221,6 +221,45 @@ export default { return matched; } }, + watch: { + valueToRender(newValueToRender, oldValueToRender) { + const newSelectionKeys = { ...this.selectionKeys }; + + const recalculateSelection = (nodes) => { + nodes.forEach((node) => { + if (node.children && node.children.length) { + recalculateSelection(node.children); + + let allChecked = true; + let someChecked = false; + + node.children.forEach((child) => { + if (newSelectionKeys[child.key]?.checked) { + someChecked = true; + } else if (newSelectionKeys[child.key]?.partialChecked) { + someChecked = true; + allChecked = false; + } else { + allChecked = false; + } + }); + + if (allChecked) { + newSelectionKeys[node.key] = { checked: true, partialChecked: false }; + } else if (someChecked) { + newSelectionKeys[node.key] = { checked: false, partialChecked: true }; + } else { + delete newSelectionKeys[node.key]; + } + } + }); + }; + + recalculateSelection(newValueToRender); + + this.$emit('update:selectionKeys', newSelectionKeys); + } + }, computed: { filteredValue() { let filteredNodes = []; From 791b4d727cb3bb84938f92b2630e4901916806b4 Mon Sep 17 00:00:00 2001 From: Emre AKA Date: Sat, 14 Dec 2024 20:18:49 +0300 Subject: [PATCH 2/2] refactor(tree): refacted selection recalculation --- packages/primevue/src/tree/Tree.vue | 67 ++++++++++++++++------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/packages/primevue/src/tree/Tree.vue b/packages/primevue/src/tree/Tree.vue index 5070d7c160..6cb8b19c2e 100755 --- a/packages/primevue/src/tree/Tree.vue +++ b/packages/primevue/src/tree/Tree.vue @@ -222,42 +222,51 @@ export default { } }, watch: { - valueToRender(newValueToRender, oldValueToRender) { - const newSelectionKeys = { ...this.selectionKeys }; + valueToRender(newValueToRender) { + const _selectionKeys = { ...this.selectionKeys }; + + const getChildrenSelection = (node) => { + const selection = { allChecked: true, someChecked: false }; + + for (const childNode of node.children) { + const keyState = _selectionKeys[childNode.key]; + + if (keyState?.checked) { + selection.someChecked = true; + } else if (keyState?.partialChecked) { + selection.someChecked = true; + selection.allChecked = false; + } else { + selection.allChecked = false; + } + } + + return selection; + }; const recalculateSelection = (nodes) => { - nodes.forEach((node) => { - if (node.children && node.children.length) { - recalculateSelection(node.children); - - let allChecked = true; - let someChecked = false; - - node.children.forEach((child) => { - if (newSelectionKeys[child.key]?.checked) { - someChecked = true; - } else if (newSelectionKeys[child.key]?.partialChecked) { - someChecked = true; - allChecked = false; - } else { - allChecked = false; - } - }); - - if (allChecked) { - newSelectionKeys[node.key] = { checked: true, partialChecked: false }; - } else if (someChecked) { - newSelectionKeys[node.key] = { checked: false, partialChecked: true }; - } else { - delete newSelectionKeys[node.key]; - } + for (const node of nodes) { + if (!node.children || !node.children.length) { + continue; } - }); + + recalculateSelection(node.children); + + const { allChecked, someChecked } = getChildrenSelection(node); + + if (allChecked) { + _selectionKeys[node.key] = { checked: true, partialChecked: false }; + } else if (someChecked) { + _selectionKeys[node.key] = { checked: false, partialChecked: true }; + } else { + delete _selectionKeys[node.key]; + } + } }; recalculateSelection(newValueToRender); - this.$emit('update:selectionKeys', newSelectionKeys); + this.$emit('update:selectionKeys', _selectionKeys); } }, computed: {