inline-editing.vue 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. <template>
  2. <div style="height: 400px">
  3. <el-auto-resizer>
  4. <template #default="{ height, width }">
  5. <el-table-v2
  6. :columns="columns"
  7. :data="data"
  8. :width="width"
  9. :height="height"
  10. fixed
  11. />
  12. </template>
  13. </el-auto-resizer>
  14. </div>
  15. </template>
  16. <script lang="tsx" setup>
  17. import { ref } from 'vue'
  18. import { ElInput } from 'element-plus'
  19. import type { FunctionalComponent } from 'vue'
  20. import type { Column, InputInstance } from 'element-plus'
  21. type SelectionCellProps = {
  22. value: string
  23. intermediate?: boolean
  24. onChange: (value: string) => void
  25. forwardRef: (el: InputInstance) => void
  26. }
  27. const InputCell: FunctionalComponent<SelectionCellProps> = ({
  28. value,
  29. onChange,
  30. forwardRef,
  31. }) => {
  32. return (
  33. <ElInput ref={forwardRef as any} onInput={onChange} modelValue={value} />
  34. )
  35. }
  36. const generateColumns = (length = 10, prefix = 'column-', props?: any) =>
  37. Array.from({ length }).map((_, columnIndex) => ({
  38. ...props,
  39. key: `${prefix}${columnIndex}`,
  40. dataKey: `${prefix}${columnIndex}`,
  41. title: `Column ${columnIndex}`,
  42. width: 150,
  43. }))
  44. const generateData = (
  45. columns: ReturnType<typeof generateColumns>,
  46. length = 200,
  47. prefix = 'row-'
  48. ) =>
  49. Array.from({ length }).map((_, rowIndex) => {
  50. return columns.reduce(
  51. (rowData, column, columnIndex) => {
  52. rowData[column.dataKey] = `Row ${rowIndex} - Col ${columnIndex}`
  53. return rowData
  54. },
  55. {
  56. id: `${prefix}${rowIndex}`,
  57. editing: false,
  58. parentId: null,
  59. }
  60. )
  61. })
  62. const columns: Column<any>[] = generateColumns(10)
  63. columns[0] = {
  64. ...columns[0],
  65. title: 'Editable Column',
  66. cellRenderer: ({ rowData, column }) => {
  67. const onChange = (value: string) => {
  68. rowData[column.dataKey!] = value
  69. }
  70. const onEnterEditMode = () => {
  71. rowData.editing = true
  72. }
  73. const onExitEditMode = () => (rowData.editing = false)
  74. const input = ref()
  75. const setRef = (el) => {
  76. input.value = el
  77. if (el) {
  78. el.focus?.()
  79. }
  80. }
  81. return rowData.editing ? (
  82. <InputCell
  83. forwardRef={setRef}
  84. value={rowData[column.dataKey!]}
  85. onChange={onChange}
  86. onBlur={onExitEditMode}
  87. onKeydownEnter={onExitEditMode}
  88. />
  89. ) : (
  90. <div class="table-v2-inline-editing-trigger" onClick={onEnterEditMode}>
  91. {rowData[column.dataKey!]}
  92. </div>
  93. )
  94. },
  95. }
  96. const data = ref(generateData(columns, 200))
  97. </script>
  98. <style>
  99. .table-v2-inline-editing-trigger {
  100. border: 1px transparent dotted;
  101. padding: 4px;
  102. }
  103. .table-v2-inline-editing-trigger:hover {
  104. border-color: var(--el-color-primary);
  105. }
  106. </style>