diff --git a/packages/components/tree-select/__tests__/tree-select.test.tsx b/packages/components/tree-select/__tests__/tree-select.test.tsx index 03c1223c2b..31de9900f6 100644 --- a/packages/components/tree-select/__tests__/tree-select.test.tsx +++ b/packages/components/tree-select/__tests__/tree-select.test.tsx @@ -725,6 +725,63 @@ describe('TreeSelect.vue', () => { expect(modelValue.value).toEqual([]) }) + test('cached checked node and use lazy multiple', async () => { + const modelValue = ref([5]) + const cacheData = reactive([{ value: 5, label: 'lazy load node5' }]) + let id = 0 + const { tree, select } = createComponent({ + props: { + modelValue, + multiple: true, + showCheckbox: true, + checkStrictly: false, + lazy: true, + load: (node: object, resolve: (p: any) => any[]) => { + resolve([ + { + value: ++id, + label: `lazy load node${id}`, + }, + { + value: ++id, + label: `lazy load node${id}`, + isLeaf: true, + }, + ]) + }, + cacheData, + }, + }) + + await nextTick() + + const node1Checkbox = tree + .findAll('.el-tree-node__content')[0] + .find('.el-checkbox') + await node1Checkbox.trigger('click') + await nextTick() + expect(select.vm.modelValue).toEqual([5, 1]) + + const node2Checkbox = tree + .findAll('.el-tree-node__content')[1] + .find('.el-checkbox') + await node2Checkbox.trigger('click') + await nextTick() + + expect(select.vm.modelValue).toEqual([5, 1, 2]) + + const node1 = tree.findAll('.el-tree-node__content')[0] + await node1.trigger('click') + await nextTick() + expect(select.vm.modelValue).toEqual([5, 3, 4, 2]) + + const node2 = tree.findAll('.el-tree-node__content')[1] + await node2.trigger('click') + await nextTick() + + expect(select.vm.modelValue).toEqual([5, 6, 4, 2]) + }) + test('no checkbox and check on click node', async () => { const { select, tree } = createComponent({ props: { diff --git a/packages/components/tree-select/src/tree.ts b/packages/components/tree-select/src/tree.ts index 9de3f2c06e..a4d70e85e4 100644 --- a/packages/components/tree-select/src/tree.ts +++ b/packages/components/tree-select/src/tree.ts @@ -1,8 +1,8 @@ // @ts-nocheck import { computed, nextTick, toRefs, watch } from 'vue' -import { isEqual, pick } from 'lodash-unified' +import { isEqual, isNil, pick } from 'lodash-unified' import { UPDATE_MODEL_EVENT } from '@element-plus/constants' -import { escapeStringRegexp, isFunction } from '@element-plus/utils' +import { escapeStringRegexp, isEmpty, isFunction } from '@element-plus/utils' import ElTree from '@element-plus/components/tree' import TreeSelectOption from './tree-select-option' import { @@ -113,6 +113,13 @@ export const useTree = ( return options }) + const getChildCheckedKeys = () => { + return tree.value?.getCheckedKeys().filter((checkedKey) => { + const node = tree.value?.getNode(checkedKey) as Node + return !isNil(node) && isEmpty(node.childNodes) + }) + } + return { ...pick(toRefs(props), Object.keys(ElTree.props)), ...attrs, @@ -208,10 +215,9 @@ export const useTree = ( // only can select leaf node else { if (props.multiple) { - emit( - UPDATE_MODEL_EVENT, - cachedKeys.concat((tree.value as TreeInstance).getCheckedKeys(true)) - ) + const childKeys = getChildCheckedKeys() + + emit(UPDATE_MODEL_EVENT, cachedKeys.concat(childKeys)) } else { // select first leaf node when check parent const firstLeaf = treeFind( @@ -258,6 +264,35 @@ export const useTree = ( select.value?.focus() }, + onNodeExpand: (data, node, e) => { + attrs.onNodeExpand?.(data, node, e) + nextTick(() => { + if ( + !props.checkStrictly && + props.lazy && + props.multiple && + node.checked + ) { + const dataMap = {} + const uncachedCheckedKeys = ( + tree.value as TreeInstance + ).getCheckedKeys() + + treeEach( + [tree.value.store.root], + (node) => (dataMap[node.key] = node), + (node) => node.childNodes + ) + + const cachedKeys = toValidArray(props.modelValue).filter( + (item) => !(item in dataMap) && !uncachedCheckedKeys.includes(item) + ) + + const childKeys = getChildCheckedKeys() + emit(UPDATE_MODEL_EVENT, cachedKeys.concat(childKeys)) + } + }) + }, // else cacheOptions, } diff --git a/packages/components/tree/src/tree-node.vue b/packages/components/tree/src/tree-node.vue index 500bb400c4..1724743662 100644 --- a/packages/components/tree/src/tree-node.vue +++ b/packages/components/tree/src/tree-node.vue @@ -270,8 +270,9 @@ export default defineComponent({ tree.ctx.emit('node-collapse', props.node.data, props.node, instance) props.node.collapse() } else { - props.node.expand() - ctx.emit('node-expand', props.node.data, props.node, instance) + props.node.expand(() => { + ctx.emit('node-expand', props.node.data, props.node, instance) + }) } }