mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
fix(components): [table] prevent child node selection loss during table data modification (#20322)
* fix(components): [table] child selection loss during data modification * refactor: replace logical AND (&&) with explicit if statement * test: use unique id
This commit is contained in:
@@ -338,6 +338,92 @@ describe('table column', () => {
|
||||
expect(expectIndexs).toEqual(actualIndexs)
|
||||
expect(wrapper.vm.selected.length).toBe(wrapper.vm.testData.length)
|
||||
})
|
||||
|
||||
// #20292
|
||||
it('Maintain child selection states during data updates', async () => {
|
||||
const wrapper = mount({
|
||||
components: {
|
||||
ElTable,
|
||||
ElTableColumn,
|
||||
},
|
||||
template: `
|
||||
<el-table ref="tableRef" :data="testData" row-key="id" default-expand-all>
|
||||
<el-table-column type="selection" />
|
||||
<el-table-column prop="desc" />
|
||||
</el-table>
|
||||
`,
|
||||
|
||||
data() {
|
||||
return {
|
||||
testData: [
|
||||
{ id: 0, desc: 'record 1' },
|
||||
{ id: 1, desc: 'record 2' },
|
||||
{
|
||||
id: 2,
|
||||
desc: 'record 3',
|
||||
children: [
|
||||
{ id: 3, desc: 'record 3-1' },
|
||||
{ id: 4, desc: 'record 3-2' },
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
addRow() {
|
||||
this.testData.push({ id: 5, desc: 'record 4' })
|
||||
},
|
||||
removeRow() {
|
||||
this.testData.pop()
|
||||
},
|
||||
removeChildRow() {
|
||||
this.testData[2].children.pop()
|
||||
},
|
||||
},
|
||||
})
|
||||
await doubleWait()
|
||||
|
||||
const getSelection = wrapper.vm.$refs.tableRef.getSelectionRows
|
||||
const domArr = wrapper.findAll('.el-table__row .el-checkbox')
|
||||
|
||||
let selectionKeys = []
|
||||
|
||||
domArr.forEach(
|
||||
(checkbox, index) => index < 3 && checkbox.trigger('click')
|
||||
)
|
||||
await doubleWait()
|
||||
|
||||
selectionKeys = getSelection().map((item) => item.id)
|
||||
expect(selectionKeys).toEqual([0, 1, 2, 3, 4])
|
||||
|
||||
// add
|
||||
wrapper.vm.addRow()
|
||||
await doubleWait()
|
||||
|
||||
selectionKeys = getSelection().map((item) => item.id)
|
||||
expect(selectionKeys).toEqual([0, 1, 2, 3, 4])
|
||||
|
||||
// remove
|
||||
wrapper.vm.removeRow()
|
||||
await doubleWait()
|
||||
|
||||
selectionKeys = getSelection().map((item) => item.id)
|
||||
expect(selectionKeys).toEqual([0, 1, 2, 3, 4])
|
||||
|
||||
// remove child
|
||||
wrapper.vm.removeChildRow()
|
||||
await doubleWait()
|
||||
|
||||
selectionKeys = getSelection().map((item) => item.id)
|
||||
expect(selectionKeys).toEqual([0, 1, 2, 3])
|
||||
|
||||
// remove with child
|
||||
wrapper.vm.removeRow()
|
||||
await doubleWait()
|
||||
|
||||
selectionKeys = getSelection().map((item) => item.id)
|
||||
expect(selectionKeys).toEqual([0, 1])
|
||||
})
|
||||
})
|
||||
|
||||
describe('= index', () => {
|
||||
|
||||
@@ -193,7 +193,8 @@ function useWatcher<T>() {
|
||||
let deleted
|
||||
if (rowKey.value) {
|
||||
deleted = []
|
||||
const dataMap = getKeysMap(data.value, rowKey.value)
|
||||
const childrenKey = instance?.store?.states?.childrenColumnName.value
|
||||
const dataMap = getKeysMap(data.value, rowKey.value, true, childrenKey)
|
||||
for (const key in selectedMap.value) {
|
||||
if (hasOwn(selectedMap.value, key) && !dataMap[key]) {
|
||||
deleted.push(selectedMap.value[key].row)
|
||||
|
||||
@@ -196,12 +196,24 @@ export const getRowIdentity = <T>(
|
||||
|
||||
export const getKeysMap = function <T>(
|
||||
array: T[],
|
||||
rowKey: string
|
||||
rowKey: string,
|
||||
flatten = false,
|
||||
childrenKey = 'children'
|
||||
): Record<string, { row: T; index: number }> {
|
||||
const data = array || []
|
||||
const arrayMap = {}
|
||||
;(array || []).forEach((row, index) => {
|
||||
|
||||
data.forEach((row, index) => {
|
||||
arrayMap[getRowIdentity(row, rowKey)] = { row, index }
|
||||
|
||||
if (flatten) {
|
||||
const children = row[childrenKey]
|
||||
if (isArray(children)) {
|
||||
Object.assign(arrayMap, getKeysMap(children, rowKey, true, childrenKey))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return arrayMap
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user