mirror of
https://github.com/element-plus/element-plus.git
synced 2024-11-21 01:02:59 +08:00
improvement(components): [virtual-table] (#7548)
- Add example for selection. - Add example for inline editing.
This commit is contained in:
parent
43cf294f8c
commit
9b3a88811d
@ -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.
|
||||
|
117
docs/examples/table-v2/inline-editing.vue
Normal file
117
docs/examples/table-v2/inline-editing.vue
Normal 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>
|
103
docs/examples/table-v2/selection.vue
Normal file
103
docs/examples/table-v2/selection.vue
Normal 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>
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user