Skip to content

Commit

Permalink
fix(components): [table] fixed column supported in grouped header (#1…
Browse files Browse the repository at this point in the history
…0096)

* fix(components): [table] fixed column supported in grouped header

* fix(components): [table] fixed column supported in grouped header

* fix(components): [table] fixed column supported in grouped header

* fix(components): [table] fixed column supported in grouped header
  • Loading branch information
tinyfind committed Oct 23, 2022
1 parent dec859a commit 9285109
Show file tree
Hide file tree
Showing 7 changed files with 218 additions and 53 deletions.
10 changes: 10 additions & 0 deletions docs/en-US/component/table.md
Expand Up @@ -95,6 +95,16 @@ table/grouping-header

:::

## Table with fixed group header

fixed group head is supported

:::demo The attribute `fixed` of the group header is determined by the outermost `el-table-column`

table/fixed-column-and-group-header

:::

## Single select

Single row selection is supported.
Expand Down
73 changes: 73 additions & 0 deletions docs/examples/table/fixed-column-and-group-header.vue
@@ -0,0 +1,73 @@
<template>
<el-table :data="tableData" style="width: 100%" height="250">
<el-table-column prop="date" label="Date" width="150" />
<el-table-column prop="name" label="Name" width="150" />
<el-table-column prop="zip" label="Zip" width="150" />
<el-table-column label="Address Info" fixed="right">
<el-table-column prop="state" label="State" width="100" />
<el-table-column prop="city" label="City" width="120" />
<el-table-column prop="address" label="Address" width="250" />
</el-table-column>
</el-table>
</template>

<script lang="ts" setup>
const tableData = [
{
date: '2016-05-03',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-02',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-04',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-01',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-08',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-06',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-07',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
]
</script>
62 changes: 62 additions & 0 deletions packages/components/table/__tests__/table-column.test.ts
Expand Up @@ -701,6 +701,68 @@ describe('table column', () => {
wrapper.unmount()
})

it('should work with fixed', async () => {
const wrapper = mount({
components: {
ElTable,
ElTableColumn,
},
template: `
<el-table :data="testData">
<el-table-column prop="name" />
<el-table-column label="group" fixed="left">
<el-table-column label="group's group">
<el-table-column prop="runtime" width="100" fixed="right"/>
<el-table-column prop="director" width="100" fixed="right"/>
</el-table-column>
<el-table-column prop="director"/>
</el-table-column>
<el-table-column prop="director"/>
<el-table-column prop="runtime"/>
<el-table-column label="group2" fixed="right">
<el-table-column prop="runtime" width="100" fixed="left"/>
<el-table-column prop="director" width="50"/>
</el-table-column>
<el-table-column prop="runtime"/>
</el-table>
`,

created() {
this.testData = getTestData()
},
})

await doubleWait()
const lfhcolumns = wrapper
.findAll('.el-table__header tr')
.map((item) => item.findAll('.el-table-fixed-column--left'))
const lfbcolumns = wrapper.findAll(
'.el-table__body .el-table-fixed-column--left'
)
const rfhcolumns = wrapper
.findAll('.el-table__header tr')
.map((item) => item.findAll('.el-table-fixed-column--right'))
const rfbcolumns = wrapper.findAll(
'.el-table__body .el-table-fixed-column--right'
)
expect(lfbcolumns).toHaveLength(15)
expect(rfbcolumns).toHaveLength(10)
expect(lfhcolumns.at(0).at(0).classes()).toContain('is-last-column')
expect(lfhcolumns.at(1).at(1).classes()).toContain('is-last-column')
expect(getComputedStyle(lfhcolumns.at(1).at(1).element).left).toBe(
'200px'
)
expect(getComputedStyle(lfhcolumns.at(2).at(1).element).left).toBe(
'100px'
)
expect(rfhcolumns.at(0).at(0).classes()).toContain('is-first-column')
expect(rfhcolumns.at(1).at(0).classes()).toContain('is-first-column')
expect(getComputedStyle(rfhcolumns.at(1).at(0).element).right).toBe(
'50px'
)
wrapper.unmount()
})

it('el-table-column should callback itself', async () => {
const TableColumn = {
name: 'TableColumn',
Expand Down
11 changes: 11 additions & 0 deletions packages/components/table/src/store/watcher.ts
Expand Up @@ -84,8 +84,19 @@ function useWatcher<T>() {
if (!rowKey.value) throw new Error('[ElTable] prop row-key is required')
}

// 更新 fixed
const updateChildFixed = (column: TableColumnCtx<T>) => {
column.children?.forEach((childColumn) => {
childColumn.fixed = column.fixed
updateChildFixed(childColumn)
})
}

// 更新列
const updateColumns = () => {
_columns.value.forEach((column) => {
updateChildFixed(column)
})
fixedColumns.value = _columns.value.filter(
(column) => column.fixed === true || column.fixed === 'left'
)
Expand Down
26 changes: 13 additions & 13 deletions packages/components/table/src/table-body/styles-helper.ts
Expand Up @@ -67,9 +67,11 @@ function useStyles<T>(props: Partial<TableBodyProps<T>>) {
column,
})
}
const fixedStyle = column.isSubColumn
? null
: getFixedColumnOffset(columnIndex, props?.fixed, props.store)
const fixedStyle = getFixedColumnOffset(
columnIndex,
props?.fixed,
props.store
)
ensurePosition(fixedStyle, 'left')
ensurePosition(fixedStyle, 'right')
return Object.assign({}, cellStyles, fixedStyle)
Expand All @@ -82,16 +84,14 @@ function useStyles<T>(props: Partial<TableBodyProps<T>>) {
column: TableColumnCtx<T>,
offset: number
) => {
const fixedClasses = column.isSubColumn
? []
: getFixedColumnsClass(
ns.b(),
columnIndex,
props?.fixed,
props.store,
undefined,
offset
)
const fixedClasses = getFixedColumnsClass(
ns.b(),
columnIndex,
props?.fixed,
props.store,
undefined,
offset
)
const classes = [column.id, column.align, column.className, ...fixedClasses]
const cellClassName = parent?.props.cellClassName
if (typeof cellClassName === 'string') {
Expand Down
30 changes: 13 additions & 17 deletions packages/components/table/src/table-header/style.helper.ts
Expand Up @@ -48,14 +48,12 @@ function useStyle<T>(props: TableHeaderProps<T>) {
column,
})
}
const fixedStyle = column.isSubColumn
? null
: getFixedColumnOffset<T>(
columnIndex,
column.fixed,
props.store,
row as unknown as TableColumnCtx<T>[]
)
const fixedStyle = getFixedColumnOffset<T>(
columnIndex,
column.fixed,
props.store,
row as unknown as TableColumnCtx<T>[]
)
ensurePosition(fixedStyle, 'left')
ensurePosition(fixedStyle, 'right')
return Object.assign({}, headerCellStyles, fixedStyle)
Expand All @@ -67,15 +65,13 @@ function useStyle<T>(props: TableHeaderProps<T>) {
row: T,
column: TableColumnCtx<T>
) => {
const fixedClasses = column.isSubColumn
? []
: getFixedColumnsClass<T>(
ns.b(),
columnIndex,
column.fixed,
props.store,
row as unknown as TableColumnCtx<T>[]
)
const fixedClasses = getFixedColumnsClass<T>(
ns.b(),
columnIndex,
column.fixed,
props.store,
row as unknown as TableColumnCtx<T>[]
)
const classes = [
column.id,
column.order,
Expand Down
59 changes: 36 additions & 23 deletions packages/components/table/src/util.ts
@@ -1,6 +1,6 @@
// @ts-nocheck
import { createPopper } from '@popperjs/core'
import { get } from 'lodash-unified'
import { flatMap, get } from 'lodash-unified'
import escapeHtml from 'escape-html'
import { hasOwn, throwError } from '@element-plus/utils'
import { useZIndex } from '@element-plus/hooks'
Expand Down Expand Up @@ -379,6 +379,18 @@ export function createTablePopper(
return popperInstance
}

function getCurrentColumns<T>(column: TableColumnCtx<T>): TableColumnCtx<T>[] {
if (column.children) {
return flatMap(column.children, getCurrentColumns)
} else {
return [column]
}
}

function getColSpan<T>(colSpan: number, column: TableColumnCtx<T>) {
return colSpan + column.colSpan
}

export const isFixedColumn = <T>(
index: number,
fixed: string | boolean,
Expand All @@ -387,21 +399,18 @@ export const isFixedColumn = <T>(
) => {
let start = 0
let after = index
const columns = store.states.columns.value
if (realColumns) {
if (realColumns[index].colSpan > 1) {
// fixed column not supported in grouped header
return {}
}
// handle group
for (let i = 0; i < index; i++) {
start += realColumns[i].colSpan
}
after = start + realColumns[index].colSpan - 1
// fixed column supported in grouped header
const curColumns = getCurrentColumns(realColumns[index])
const preColumns = columns.slice(0, columns.indexOf(curColumns[0]))

start = preColumns.reduce(getColSpan, 0)
after = start + curColumns.reduce(getColSpan, 0) - 1
} else {
start = index
}
let fixedLayout
const columns = store.states.columns
switch (fixed) {
case 'left':
if (after < store.states.fixedLeafColumnsLength.value) {
Expand All @@ -411,7 +420,7 @@ export const isFixedColumn = <T>(
case 'right':
if (
start >=
columns.value.length - store.states.rightFixedLeafColumnsLength.value
columns.length - store.states.rightFixedLeafColumnsLength.value
) {
fixedLayout = 'right'
}
Expand All @@ -421,7 +430,7 @@ export const isFixedColumn = <T>(
fixedLayout = 'left'
} else if (
start >=
columns.value.length - store.states.rightFixedLeafColumnsLength.value
columns.length - store.states.rightFixedLeafColumnsLength.value
) {
fixedLayout = 'right'
}
Expand All @@ -444,13 +453,18 @@ export const getFixedColumnsClass = <T>(
offset = 0
) => {
const classes: string[] = []
const { direction, start } = isFixedColumn(index, fixed, store, realColumns)
const { direction, start, after } = isFixedColumn(
index,
fixed,
store,
realColumns
)
if (direction) {
const isLeft = direction === 'left'
classes.push(`${namespace}-fixed-column--${direction}`)
if (
isLeft &&
start + offset === store.states.fixedLeafColumnsLength.value - 1
after + offset === store.states.fixedLeafColumnsLength.value - 1
) {
classes.push('is-last-column')
} else if (
Expand Down Expand Up @@ -480,23 +494,22 @@ export const getFixedColumnOffset = <T>(
store: any,
realColumns?: TableColumnCtx<T>[]
) => {
const { direction, start = 0 } = isFixedColumn(
index,
fixed,
store,
realColumns
)
const {
direction,
start = 0,
after = 0,
} = isFixedColumn(index, fixed, store, realColumns)
if (!direction) {
return
}
const styles: any = {}
const isLeft = direction === 'left'
const columns = store.states.columns.value
if (isLeft) {
styles.left = columns.slice(0, index).reduce(getOffset, 0)
styles.left = columns.slice(0, start).reduce(getOffset, 0)
} else {
styles.right = columns
.slice(start + 1)
.slice(after + 1)
.reverse()
.reduce(getOffset, 0)
}
Expand Down

0 comments on commit 9285109

Please sign in to comment.