Skip to content

Table enhancements ​

DragSortTable, RowEditorTable and CellEditorTable share ProTable schemas, requests, native configuration and semantic styles. They add reordering, row editing and cell editing respectively.

vue
<script setup lang="ts">
import { ref } from 'vue'
import { Button, Space } from 'antdv-next'
import {
  CellEditorTable,
  DragSortTable,
  RowEditorTable,
  type EditableConfig,
  type ProColumns,
  type ProKey,
  type ProTableInstance,
} from '@bubblesjs/antv-next-pro'

interface Task extends Record<string, unknown> {
  id: number
  name: string
  priority: number
}
const initial: Task[] = [
  { id: 1, name: '编写示例', priority: 1 },
  { id: 2, name: '交互验收', priority: 2 },
  { id: 3, name: '整理文档', priority: 3 },
]
const columns: ProColumns<Task>[] = [
  {
    title: '任务',
    dataIndex: 'name',
    formItemProps: { rules: [{ required: true, message: '请输入任务名称' }] },
  },
  { title: '优先级', dataIndex: 'priority', valueType: 'digit', fieldProps: { min: 1, max: 5 } },
]
const dragRows = ref(initial.map((row) => ({ ...row })))
const rowRows = ref(initial.map((row) => ({ ...row })))
const cellRows = ref(initial.map((row) => ({ ...row })))
const rowAction = ref<ProTableInstance<Task>>()
const cellAction = ref<ProTableInstance<Task>>()
const feedback = ref('拖动手柄排序;也可以聚焦手柄后按上下方向键。')
const editable: EditableConfig<Task> = {
  type: 'single',
  onSave: async (_key, record) => {
    feedback.value = `已保存任务:${record.name}`
    return true
  },
}
function dragEnd(from: number, to: number, rows: Task[]) {
  feedback.value = `第 ${from + 1} 项移至第 ${to + 1} 项;当前顺序:${rows.map((row) => row.name).join('、')}`
}
function begin(_key: ProKey, record: Task) {
  feedback.value = `正在编辑:${record.name}`
}
function end(_key: ProKey, record: Task) {
  feedback.value = `编辑结束:${record.name}`
}
</script>

<template>
  <div class="enhanced-demo" data-demo="table-enhancements">
    <section data-demo-drag-table>
      <h3>拖动排序</h3>
      <p>拖动行首手柄,或聚焦手柄后按 ↑ / ↓。排序结果保存在当前页面。</p>
      <DragSortTable
        v-model:data-source="dragRows"
        row-key="id"
        :columns="columns"
        :search="false"
        :options="false"
        :pagination="false"
        :tool-bar-render="false"
        @drag-sort-end="dragEnd"
      />
    </section>
    <section data-demo-row-table>
      <h3>行编辑</h3>
      <p>双击一行进入编辑,焦点离开当前行后保存;按钮也可启动、保存和取消。</p>
      <Space class="actions">
        <Button data-demo-row-start @click="rowAction?.startEditable(1)">编辑第一行</Button>
        <Button data-demo-row-save @click="rowAction?.saveEditable(1)">保存第一行</Button>
        <Button data-demo-row-cancel @click="rowAction?.cancelEditable(1)">取消编辑</Button>
      </Space>
      <RowEditorTable
        ref="rowAction"
        v-model:data-source="rowRows"
        row-key="id"
        :columns="columns"
        :editable="editable"
        :search="false"
        :options="false"
        :pagination="false"
        :tool-bar-render="false"
        :on-row-edit-start="begin"
        :on-row-edit-end="end"
      />
    </section>
    <section data-demo-cell-table>
      <h3>单元格编辑</h3>
      <p>双击名称或优先级,只编辑当前单元格;切换单元格时先保存并校验。</p>
      <Space class="actions">
        <Button data-demo-cell-start @click="cellAction?.startEditable(1)">编辑首个单元格</Button>
        <Button data-demo-cell-save @click="cellAction?.saveEditable(1)">保存第一行</Button>
        <Button data-demo-cell-cancel @click="cellAction?.cancelEditable(1)">取消编辑</Button>
      </Space>
      <CellEditorTable
        ref="cellAction"
        v-model:data-source="cellRows"
        row-key="id"
        :columns="columns"
        :editable="editable"
        :search="false"
        :options="false"
        :pagination="false"
        :tool-bar-render="false"
        :on-row-edit-start="begin"
        :on-row-edit-end="end"
      />
    </section>
    <p data-demo-enhanced-state aria-live="polite">{{ feedback }}</p>
  </div>
</template>

<style scoped>
.enhanced-demo {
  display: grid;
  gap: 28px;
}
h3 {
  margin-block: 0 8px;
}
p {
  margin-block: 0 16px;
}
.actions {
  margin-block-end: 12px;
}
</style>

Minimal usage ​

vue
<script setup lang="ts">
import { ref } from 'vue'
import { DragSortTable, type ProColumns } from '@bubblesjs/antv-next-pro'

type Task = { id: number; title: string }
const rows = ref<Task[]>([
  { id: 1, title: 'Plan work' },
  { id: 2, title: 'Verify changes' },
])
const columns: ProColumns<Task>[] = [{ title: 'Task', dataIndex: 'title' }]
</script>

<template>
  <DragSortTable
    v-model:dataSource="rows"
    row-key="id"
    :columns="columns"
    :search="false"
    :pagination="false"
  />
</template>

DragSortTable ​

Extends ProTable props and exposes ProTableInstance. Generic parameters are record type T and request parameter type P.

Prop/eventBehavior
dragSortKeyHandle column key or dataIndex, default __dragSort; a missing column is inserted first
dragSortHandlerRender(record, index) => VNodeChild, custom handle content
v-model:dataSourceControlled rows; the parent must accept the reordered array
defaultDataSourceUncontrolled initial rows
dragSortEnd(beforeIndex, afterIndex, rows)Reorder notification with the resulting full row array
dataSourceChange(rows)Data order notification

Handles support drag and keyboard Up/Down. Event indexes refer to positions in the current data source; they are not permanent database ranks. Controlled mode waits for parent acceptance. Persist changes in your event handler; returning a Promise does not provide automatic rollback.

The default handle class is ant-pro-table-drag-icon and follows the global or component prefix.

RowEditorTable ​

Extends EditableProTable. Double-click a row to edit it. Focus leaving the row schedules validation and save after 150ms; moving focus inside the same row does not save. Editable type defaults to single and the record creator button defaults to false; explicit settings override these defaults.

Prop/eventBehavior
editableValidation, onSave, onCancel, editableKeys, native formRef and other editing settings
onRowEditStart(key, record)Called on entry to editing
onRowEditEnd(key, record)Called after successful save, cancellation or key removal
onRowNative row bindings; the original double-click handler runs first, and preventDefault blocks activation
v-model:editableKeysControlled editing key updates

False from editable.onSave or failed validation keeps the row open. Editable formRef receives the actual native FormInstance. DataSource, value and editing result conventions follow EditableProTable.

CellEditorTable ​

Extends RowEditorTable configuration and callbacks. Double-click an editable cell to show its input. Focus leaving the cell saves after 150ms. Activating another cell first saves the current edit; failed validation prevents switching.

Readonly, editable=false and option columns cannot be edited. The original column.onCell double-click callback runs first and may preventDefault to block activation. Calling startEditable(key) selects the first editable field in that row.

Slots, ref and styles ​

All three forward table slots and ProTableInstance methods for requests, data, pagination, selection and editing, including startEditable, saveEditable and cancelEditable. Row/Cell instance editing methods also maintain their editing lifecycle callbacks.

Column render uses (dom, record, index, action, schema). Custom editing uses formItemRender(schema, context, nativeForm), with native Form validation.

PrefixCls, classes and styles follow ProTable/EditableProTable. Classes/styles accept a map or ({ props }) => map; legacy classNames remains compatible. Locale, RTL, native theme and Pro extension tokens follow ProConfigProvider conventions.

Boundaries ​

Automatic Row/Cell editing relies on double-click and focus departure; use instance methods for explicit editing controls. The 150ms delay buffers focus changes, not network completion. Return the real save Promise from editable.onSave. DragSortTable reorders current data; cross-page remote ranking belongs to application logic.

Released under the MIT License