improvement(components): [virtual-table] (#7548)

- Add example for selection.
- Add example for inline editing.
This commit is contained in:
JeremyWuuuuu 2022-05-07 11:47:52 +08:00 committed by GitHub
parent 43cf294f8c
commit 9b3a88811d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 243 additions and 5 deletions

View File

@ -58,6 +58,26 @@ table-v2/cell-templating
:::
## Table with selections
Using customized cell renderer to allow selection for your table.
:::demo
table-v2/selection
:::
## Inline editing
Just like selections we demonstrated above, you can use the same method to enable inline editing.
:::demo
table-v2/inline-editing
:::
## Table with status
You can highlight your table content to distinguish between "success, information, warning, danger" and other states.

View File

@ -0,0 +1,117 @@
<template>
<div style="height: 400px">
<el-auto-resizer>
<template #default="{ height, width }">
<el-table-v2
:columns="columns"
:data="data"
:width="width"
:height="height"
fixed
/>
</template>
</el-auto-resizer>
</div>
</template>
<script lang="tsx" setup>
import { nextTick, ref, resolveDynamicComponent } from 'vue'
import type { FunctionalComponent } from 'vue'
import type { Column, ElInput } from 'element-plus'
const Input = resolveDynamicComponent('ElInput') as typeof ElInput
type SelectionCellProps = {
value: string
intermediate?: boolean
onChange: (value: string) => void
forwardRef: (el: InstanceType<typeof ElInput>) => void
}
const InputCell: FunctionalComponent<SelectionCellProps> = ({
value,
onChange,
forwardRef,
}) => {
return <Input ref={forwardRef as any} onInput={onChange} modelValue={value} />
}
const generateColumns = (length = 10, prefix = 'column-', props?: any) =>
Array.from({ length }).map((_, columnIndex) => ({
...props,
key: `${prefix}${columnIndex}`,
dataKey: `${prefix}${columnIndex}`,
title: `Column ${columnIndex}`,
width: 150,
}))
const generateData = (
columns: ReturnType<typeof generateColumns>,
length = 200,
prefix = 'row-'
) =>
Array.from({ length }).map((_, rowIndex) => {
return columns.reduce(
(rowData, column, columnIndex) => {
rowData[column.dataKey] = `Row ${rowIndex} - Col ${columnIndex}`
return rowData
},
{
id: `${prefix}${rowIndex}`,
editing: false,
parentId: null,
}
)
})
const columns: Column<any>[] = generateColumns(10)
columns[0] = {
...columns[0],
title: 'Editable Column',
cellRenderer: ({ rowData, column }) => {
const onChange = (value: string) => {
rowData[column.dataKey!] = value
}
const onEnterEditMode = () => {
rowData.editing = true
}
const onExitEditMode = () => (rowData.editing = false)
const input = ref()
const setRef = (el) => {
input.value = el
if (el) {
el.focus?.()
}
}
return rowData.editing ? (
<InputCell
forwardRef={setRef}
value={rowData[column.dataKey!]}
onChange={onChange}
onBlur={onExitEditMode}
onKeydownEnter={onExitEditMode}
/>
) : (
<div class="table-v2-inline-editing-trigger" onClick={onEnterEditMode}>
{rowData[column.dataKey!]}
</div>
)
},
}
const data = ref(generateData(columns, 200))
</script>
<style>
.table-v2-inline-editing-trigger {
border: 1px transparent dotted;
padding: 4px;
}
.table-v2-inline-editing-trigger:hover {
border-color: var(--el-color-primary);
}
</style>

View File

@ -0,0 +1,103 @@
<template>
<div style="height: 400px">
<el-auto-resizer>
<template #default="{ height, width }">
<el-table-v2
:columns="columns"
:data="data"
:width="width"
:height="height"
fixed
/>
</template>
</el-auto-resizer>
</div>
</template>
<script lang="tsx" setup>
import { ref, resolveDynamicComponent, unref } from 'vue'
import type { FunctionalComponent } from 'vue'
import type { Column, ElCheckbox } from 'element-plus'
const Checkbox = resolveDynamicComponent('ElCheckbox') as typeof ElCheckbox
type SelectionCellProps = {
value: boolean
intermediate?: boolean
onChange: (value: boolean) => void
}
const SelectionCell: FunctionalComponent<SelectionCellProps> = ({
value,
intermediate = false,
onChange,
}) => {
return (
<Checkbox
onChange={onChange}
modelValue={value}
indeterminate={intermediate}
/>
)
}
const generateColumns = (length = 10, prefix = 'column-', props?: any) =>
Array.from({ length }).map((_, columnIndex) => ({
...props,
key: `${prefix}${columnIndex}`,
dataKey: `${prefix}${columnIndex}`,
title: `Column ${columnIndex}`,
width: 150,
}))
const generateData = (
columns: ReturnType<typeof generateColumns>,
length = 200,
prefix = 'row-'
) =>
Array.from({ length }).map((_, rowIndex) => {
return columns.reduce(
(rowData, column, columnIndex) => {
rowData[column.dataKey] = `Row ${rowIndex} - Col ${columnIndex}`
return rowData
},
{
id: `${prefix}${rowIndex}`,
checked: false,
parentId: null,
}
)
})
const columns: Column<any>[] = generateColumns(10)
columns.unshift({
key: 'selection',
width: 50,
cellRenderer: ({ rowData }) => {
const onChange = (value: boolean) => (rowData.checked = value)
return <SelectionCell value={rowData.checked} onChange={onChange} />
},
headerCellRenderer: () => {
const _data = unref(data)
const onChange = (value: boolean) =>
(data.value = _data.map((row) => {
row.checked = value
return row
}))
const allSelected = _data.every((row) => row.checked)
const containsChecked = _data.some((row) => row.checked)
return (
<SelectionCell
value={allSelected}
intermediate={containsChecked && !allSelected}
onChange={onChange}
/>
)
},
})
const data = ref(generateData(columns, 200))
</script>

View File

@ -63,16 +63,14 @@ const useTableRow = (props: TableV2RowProps) => {
const eventHandlers = computed(() => {
const { rowData, rowIndex, rowKey, onRowHover } = props
const handlers = props.rowEventHandlers || ({} as RowEventHandlers<any>)
const handlers = props.rowEventHandlers || ({} as RowEventHandlers)
const eventHandlers = {} as {
[key in keyof RowEventHandlers<any>]: (e: Event) => void
[key in keyof RowEventHandlers]: (e: Event) => void
}
Object.entries(handlers).forEach(([eventName, handler]) => {
if (isFunction(handler)) {
eventHandlers[eventName as keyof RowEventHandlers<any>] = (
event: Event
) => {
eventHandlers[eventName as keyof RowEventHandlers] = (event: Event) => {
handler({
event,
rowData,