mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
feat(components): [table] add row-expandable prop (#23140)
* feat(components): [table] add row-expandable prop * Update table.md * fix(components): [table] refine rowExpandable and update expandable docs * fix(components): [table] refine rowExpandable --------- Co-authored-by: anhao <wzanh@sinopec.com>
This commit is contained in:
@@ -305,6 +305,7 @@ table/tooltip-formatter
|
||||
| tooltip-formatter ^(2.9.4) | customize tooltip content when using `show-overflow-tooltip` | ^[Function]`(data: { row: any, column: TableColumnCtx<T>, cellValue: any }) => VNode \| string` | — |
|
||||
| preserve-expanded-content ^(2.9.7) | whether to preserve expanded row content in DOM when collapsed | ^[boolean] | false |
|
||||
| native-scrollbar ^(2.10.5) | whether to use native scrollbars | ^[boolean] | false |
|
||||
| row-expandable ^(2.14.0) | enable expandable rows, works when the table has a column type="expand" | ^[Function]`(row: any, index: number) => boolean` | — |
|
||||
|
||||
### Table Events
|
||||
|
||||
@@ -396,12 +397,12 @@ table/tooltip-formatter
|
||||
|
||||
### Table-column Slots
|
||||
|
||||
| Name | Description | Type |
|
||||
| -------------------- | --------------------------------- | ------------------------------------------------------------------ |
|
||||
| default | Custom content for table columns | ^[object]`{ row: any, column: TableColumnCtx<T>, $index: number }` |
|
||||
| header | Custom content for table header | ^[object]`{ column: TableColumnCtx<T>, $index: number }` |
|
||||
| filter-icon ^(2.7.8) | Custom content for filter icon | ^[object]`{ filterOpened: boolean }` |
|
||||
| expand ^(2.10.0) | Custom content for expand columns | ^[object]`{ expanded: boolean }` |
|
||||
| Name | Description | Type |
|
||||
| -------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------ |
|
||||
| default | Custom content for table columns | ^[object]`{ row: any, column: TableColumnCtx<T>, $index: number }` |
|
||||
| header | Custom content for table header | ^[object]`{ column: TableColumnCtx<T>, $index: number }` |
|
||||
| filter-icon ^(2.7.8) | Custom content for filter icon | ^[object]`{ filterOpened: boolean }` |
|
||||
| expand ^(2.10.0) | Custom content for expand columns. The `expandable` property is supported starting from v2.14.0. | ^[object]`{ expanded: boolean, expandable: boolean }` |
|
||||
|
||||
## Type Declarations
|
||||
|
||||
|
||||
@@ -907,6 +907,9 @@ describe('table column', () => {
|
||||
refreshData() {
|
||||
this.testData = getTestData()
|
||||
},
|
||||
expandable(row) {
|
||||
return row.id % 2 === 0
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -918,6 +921,20 @@ describe('table column', () => {
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
it('should respect row-expandable prop', async () => {
|
||||
const wrapper = createInstance(
|
||||
':row-expandable="expandable" default-expand-all'
|
||||
)
|
||||
await doubleWait()
|
||||
expect(
|
||||
wrapper.findAll('.el-table__expand-icon--expanded').length
|
||||
).toEqual(2)
|
||||
expect(
|
||||
wrapper.findAll('.el-table__expand-icon.is-disabled').length
|
||||
).toEqual(3)
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
describe('preserve-expanded-content', () => {
|
||||
it('should lose expanded state when refreshing data without preserve-expanded-content', async () => {
|
||||
const wrapper = createInstance() // No preserve-expanded-content prop
|
||||
|
||||
@@ -127,11 +127,13 @@ export const cellForced = {
|
||||
row,
|
||||
store,
|
||||
expanded,
|
||||
$index,
|
||||
}: {
|
||||
column: TableColumnCtx<T>
|
||||
row: T
|
||||
store: Store<T>
|
||||
expanded: boolean
|
||||
$index: number
|
||||
}) {
|
||||
const { ns } = store
|
||||
const classes = [ns.e('expand-icon')]
|
||||
@@ -143,10 +145,16 @@ export const cellForced = {
|
||||
e.stopPropagation()
|
||||
store.toggleRowExpansion(row)
|
||||
}
|
||||
const isRowExpandable =
|
||||
store.states.rowExpandable.value?.(row, $index) ?? true
|
||||
if (!isRowExpandable) {
|
||||
classes.push(ns.is('disabled'))
|
||||
}
|
||||
return h(
|
||||
'button',
|
||||
{
|
||||
type: 'button',
|
||||
disabled: !isRowExpandable,
|
||||
'aria-label': store.t(
|
||||
expanded ? 'el.table.collapseRowLabel' : 'el.table.expandRowLabel'
|
||||
),
|
||||
@@ -160,6 +168,7 @@ export const cellForced = {
|
||||
return [
|
||||
column.renderExpand({
|
||||
expanded,
|
||||
expandable: isRowExpandable,
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -9,28 +9,36 @@ function useExpand<T extends DefaultRow>(watcherData: WatcherPropsData<T>) {
|
||||
const instance = getCurrentInstance() as Table<T>
|
||||
const defaultExpandAll = ref(false)
|
||||
const expandRows: Ref<T[]> = ref([])
|
||||
|
||||
const canRowExpand = (row: T, index: number) => {
|
||||
const expandableFn = instance.store.states.rowExpandable.value
|
||||
return expandableFn?.(row, index) ?? true
|
||||
}
|
||||
|
||||
const updateExpandRows = () => {
|
||||
const data = watcherData.data.value || []
|
||||
const rowKey = watcherData.rowKey.value
|
||||
if (defaultExpandAll.value) {
|
||||
expandRows.value = data.slice()
|
||||
expandRows.value = instance.store.states.rowExpandable.value
|
||||
? data.filter(canRowExpand)
|
||||
: data.slice()
|
||||
} else if (rowKey) {
|
||||
// TODO:这里的代码可以优化
|
||||
const expandRowsMap = getKeysMap(expandRows.value, rowKey)
|
||||
expandRows.value = data.reduce((prev: T[], row: T) => {
|
||||
expandRows.value = data.filter((row, index) => {
|
||||
const rowId = getRowIdentity(row, rowKey)
|
||||
const rowInfo = expandRowsMap[rowId]
|
||||
if (rowInfo) {
|
||||
prev.push(row)
|
||||
}
|
||||
return prev
|
||||
}, [])
|
||||
return !!expandRowsMap[rowId] && canRowExpand(row, index)
|
||||
})
|
||||
} else {
|
||||
expandRows.value = []
|
||||
}
|
||||
}
|
||||
|
||||
const toggleRowExpansion = (row: T, expanded?: boolean) => {
|
||||
const dataArr = watcherData.data.value || []
|
||||
const rowIndex = dataArr.indexOf(row)
|
||||
if (rowIndex > -1 && !canRowExpand(row, rowIndex)) return
|
||||
|
||||
const changed = toggleRowStatus(
|
||||
expandRows.value,
|
||||
row,
|
||||
@@ -53,7 +61,7 @@ function useExpand<T extends DefaultRow>(watcherData: WatcherPropsData<T>) {
|
||||
const keysMap = getKeysMap(data, rowKey)
|
||||
expandRows.value = rowKeys.reduce((prev: T[], cur) => {
|
||||
const info = keysMap[cur]
|
||||
if (info) {
|
||||
if (info && canRowExpand(info.row, info.index)) {
|
||||
prev.push(info.row)
|
||||
}
|
||||
return prev
|
||||
|
||||
@@ -9,6 +9,7 @@ import type { DefaultRow, Table, TableProps } from '../table/defaults'
|
||||
const InitialStateMap = {
|
||||
rowKey: 'rowKey',
|
||||
defaultExpandAll: 'defaultExpandAll',
|
||||
rowExpandable: 'rowExpandable',
|
||||
selectOnIndeterminate: 'selectOnIndeterminate',
|
||||
indent: 'indent',
|
||||
lazy: 'lazy',
|
||||
|
||||
@@ -82,6 +82,8 @@ function useWatcher<T extends DefaultRow>() {
|
||||
const reserveSelection = ref(false)
|
||||
const selectOnIndeterminate = ref(false)
|
||||
const selectable: Ref<((row: T, index: number) => boolean) | null> = ref(null)
|
||||
const rowExpandable: Ref<((row: T, index: number) => boolean) | null> =
|
||||
ref(null)
|
||||
const filters: Ref<StoreFilter> = ref({})
|
||||
const filteredData: Ref<T[] | null> = ref(null)
|
||||
const sortingColumn: Ref<TableColumnCtx<T> | null> = ref(null)
|
||||
@@ -577,6 +579,7 @@ function useWatcher<T extends DefaultRow>() {
|
||||
reserveSelection,
|
||||
selectOnIndeterminate,
|
||||
selectable,
|
||||
rowExpandable,
|
||||
filters,
|
||||
filteredData,
|
||||
sortingColumn,
|
||||
|
||||
@@ -132,6 +132,7 @@ interface TableProps<T extends DefaultRow> {
|
||||
emptyText?: string
|
||||
expandRowKeys?: Array<string>
|
||||
defaultExpandAll?: boolean
|
||||
rowExpandable?: (row: T, index: number) => boolean
|
||||
defaultSort?: Sort
|
||||
tooltipEffect?: string
|
||||
tooltipOptions?: TableOverflowTooltipOptions
|
||||
@@ -323,6 +324,12 @@ export default {
|
||||
* @description whether expand all rows by default, works when the table has a column type="expand" or contains tree structure data
|
||||
*/
|
||||
defaultExpandAll: Boolean,
|
||||
/**
|
||||
* @description enable expandable rows, works when the table has a column type="expand"
|
||||
*/
|
||||
rowExpandable: {
|
||||
type: Function as PropType<TableProps<any>['rowExpandable']>,
|
||||
},
|
||||
/**
|
||||
* @description set the default sort column and order. property `prop` is used to set default sort column, property `order` is used to set default sort order
|
||||
*/
|
||||
|
||||
@@ -87,6 +87,11 @@
|
||||
width: min(23px, 100%);
|
||||
height: 23px;
|
||||
|
||||
@include when(disabled) {
|
||||
color: getCssVar('disabled-text-color');
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
@include m(expanded) {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user