Skip to content

ProTable

Overview

ProTable is a configuration-driven advanced table component built on top of Ant Design Vue Table, with built-in search form, toolbar, pagination, and value type rendering — significantly reducing boilerplate code.

Basic Usage

vue
<script setup lang="ts">
import ProTable from '@/components/Pro/ProTable/index.vue'
import type { ProTableColumn, ProTableRequest } from '@/types/pro'

const columns: ProTableColumn[] = [
  {
    title: 'Name',
    dataIndex: 'name',
    search: true,
  },
  {
    title: 'Status',
    dataIndex: 'status',
    valueType: 'tag',
    search: true,
    options: [
      { label: 'Active', value: 'active', color: 'green' },
      { label: 'Inactive', value: 'inactive', color: 'red' },
    ],
  },
  {
    title: 'Created At',
    dataIndex: 'createdAt',
    valueType: 'dateTime',
  },
  {
    title: 'Actions',
    dataIndex: 'actions',
    actions: [
      { label: 'Edit', onClick: (record) => handleEdit(record) },
      { label: 'Delete', danger: true, confirm: 'Are you sure?', onClick: (record) => handleDelete(record) },
    ],
  },
]

const request: ProTableRequest = async (params) => {
  const res = await fetchUsers(params)
  return { data: res.list, total: res.total, success: true }
}
</script>

<template>
  <ProTable :columns="columns" :request="request" />
</template>

Props

PropTypeDefaultDescription
columnsProTableColumn[]RequiredColumn definitions
requestProTableRequestRequiredData fetching function
toolbarProTableToolbarToolbar configuration
searchProTableSearch | falseSearch form config, false to hide
headerFilterProTableHeaderFilterConfigHeader filter global config
paginationProTablePagination | falseDefault paginationPagination config, false to hide
rowKeystring | ((record) => string)'id'Row unique key
size'large' | 'middle' | 'small''small'Table density
heightnumber | string | 'auto''auto'Table height
resizablebooleantrueRow resizable
columnResizablebooleantrueColumn width drag-resizable
ellipsisbooleantrueText overflow ellipsis
borderedbooleantrueShow border
fixedHeaderbooleantrueFixed header on scroll
formItemsProFormItem[]Form config for built-in CRUD modal
formLayoutProFormLayoutCRUD modal form layout
formGridProFormGridCRUD modal form grid
formModalWidthnumber | string640CRUD modal width
formCreateTitlestring'Add'Create modal title
formEditTitlestring'Edit'Edit modal title

ProTableColumn

Column configuration interface defining rendering, search, and interaction behavior:

PropertyTypeDescription
titlestringColumn header text
dataIndexstringData field key
keystringOptional unique key
widthnumber | stringColumn width
minWidthnumber | stringMinimum column width
fixed'left' | 'right'Fixed column position
align'left' | 'center' | 'right'Text alignment
ellipsisbooleanText overflow ellipsis
resizablebooleanColumn drag-resizable
hideInTablebooleanHide column in table
valueTypeValueTypeRender type
valueEnumRecord<string, { text, status?, color? }>Enum mapping
copyablebooleanEnable copy on click
searchbooleanGenerate search field
searchTypeSearchTypeSearch field type (auto-inferred from valueType if omitted)
searchOptionsArray<{ label, value }>Search select options
optionsArray<{ label, value, color?, status?, disabled? }>Unified options — auto-derives searchOptions and valueEnum
searchPropsRecord<string, any>Extra search field props
headerFilterProTableHeaderFilterHeader filter config
sorterboolean | ((a, b) => number)Enable sorting
defaultSortOrder'ascend' | 'descend'Default sort direction
actionsProTableAction[]Action column buttons
render(text, record, index) => anyCustom render function
valueTypePropsRecord<string, any>Custom rendering params for ValueType (e.g. date format, currency symbol)

ValueType

TypeDescriptionExample
textPlain text (default)Hello
dateDate — customizable via valueTypeProps.format2024-01-15
dateTimeDate and time — customizable via valueTypeProps.format2024-01-15 14:30:00
dateRangeDate range
timeTime14:30:00
tagTag (use with valueEnum)
badgeBadge (use with valueEnum)
moneyCurrency (with symbol and formatting) — customizable via valueTypeProps.symbol and precision¥12,345.00
percentPercentage — customizable via valueTypeProps.precision85.50%
avatarAvatar (32px circle) — customizable via valueTypeProps.size
imageImage (80px width) — customizable via valueTypeProps.width
linkHyperlink
progressProgress bar

SearchType

TypeDescription
inputText input
selectSelect dropdown (requires searchOptions or valueEnum)
dateRangeDate range picker
datePickerDate picker
numberNumber input
checkboxCheckbox
radioRadio

Unified Options

Use the options property to define column options once, automatically deriving both valueEnum (for rendering) and searchOptions (for search dropdowns):

typescript
{
  title: 'Status',
  dataIndex: 'status',
  valueType: 'tag',
  search: true,
  options: [
    { label: 'Active', value: 'active', color: 'green' },
    { label: 'Inactive', value: 'inactive', color: 'red' },
  ],
}

This is equivalent to setting valueEnum + searchOptions separately, reducing configuration duplication. If both options and valueEnum/searchOptions are set, the latter takes precedence.

valueTypeProps

Customize ValueType rendering with valueTypeProps:

typescript
const columns: ProTableColumn[] = [
  {
    title: 'Created At',
    dataIndex: 'createdAt',
    valueType: 'date',
    valueTypeProps: { format: 'YYYY/MM/DD' },
  },
  {
    title: 'Amount',
    dataIndex: 'amount',
    valueType: 'money',
    valueTypeProps: { symbol: '$', precision: 0 },
  },
  {
    title: 'Progress',
    dataIndex: 'progress',
    valueType: 'progress',
    valueTypeProps: { strokeColor: '#52c41a', showInfo: true },
  },
]
ValueTypeAvailable PropsDescription
dateformatDate format, default 'YYYY-MM-DD'
dateTimeformatDateTime format, default 'YYYY-MM-DD HH:mm:ss'
moneysymbol, precisionCurrency symbol (default ¥) and decimal places (default 2)
percentprecisionDecimal places (default 2)
avatarsizeAvatar size (default 32)
imagewidthImage width (default 80)
progressAll a-progress propsPassed through to progress component

ProTableAction

Define row-level action buttons:

PropertyTypeDescription
labelstringButton text
type'link' | 'button' | 'dropdown'Button type
iconanyButton icon
permissionstringRequired permission code
dangerbooleanMark as dangerous action
disabled(record) => booleanDisable condition
hidden(record) => booleanHide condition
confirmstringConfirmation prompt (shows confirm dialog)
onClick(record) => void | Promise<void>Click handler
itemsProTableAction[]Dropdown items (when type is dropdown)
typescript
actions: [
  {
    label: 'Edit',
    permission: 'user.edit',
    onClick: (record) => openEditModal(record),
  },
  {
    label: 'More',
    type: 'dropdown',
    items: [
      { label: 'Reset Password', onClick: (record) => resetPassword(record) },
      { label: 'Delete', danger: true, confirm: 'Are you sure?', onClick: (record) => deleteUser(record) },
    ],
  },
]

ProTableHeaderFilter

Column-level header filtering with keyword search and select types:

PropertyTypeDescription
type'keyword' | 'select'Filter type
mode'client' | 'server' | 'hybrid'Filter mode
icon'search' | 'filter'Icon type
paramKeystringServer-side parameter name
placeholderstringPlaceholder text
multiplebooleanMulti-select (for select type)
optionsArray<{ label, value }>Select options

Filter modes:

  • client — Client-side filtering, no request sent
  • server — Server-side filtering, filter params included in request
  • hybrid — Fetches data via request, then filters client-side

Toolbar

typescript
const toolbar: ProTableToolbar = {
  title: 'User List',
  subTitle: 'Manage system users',
  // Prefix with ! to hide default tools
  actions: ['!density'],  // Hide density switcher
}

Built-in tools:

  • Refresh — Reload data
  • Density — Toggle table density (large/middle/small)
  • Column Settings — Column visibility, ordering, and pinning

Events

EventParamsDescription
refreshTriggered when refresh button is clicked
form-submit{ values, record, isEdit }Triggered when built-in form is submitted

Slots

SlotDescription
toolbar-actionsCustom actions area on toolbar right side
bodyCellCustom cell rendering

Built-in CRUD Modal

By configuring formItems, ProTable can embed a CRUD modal without manually managing ProModal + ProForm:

vue
<script setup lang="ts">
import ProTable from '@/components/Pro/ProTable/index.vue'
import type { ProTableColumn, ProFormItem } from '@/types/pro'

const tableRef = ref()

const columns: ProTableColumn[] = [
  { title: 'Name', dataIndex: 'name', search: true },
  { title: 'Email', dataIndex: 'email' },
  {
    title: 'Actions',
    dataIndex: 'action',
    actions: [
      { label: 'Edit', onClick: (record) => tableRef.value?.openEditModal(record) },
    ],
  },
]

const formItems: ProFormItem[] = [
  { name: 'name', label: 'Name', type: 'input', required: true },
  { name: 'email', label: 'Email', type: 'input' },
]

const handleFormSubmit = async ({ values, record, isEdit }) => {
  if (isEdit) {
    await updateUser(record.id, values)
  } else {
    await createUser(values)
  }
  tableRef.value?.refresh()
}
</script>

<template>
  <ProTable
    ref="tableRef"
    :columns="columns"
    :request="request"
    :form-items="formItems"
    :form-grid="{ cols: 2 }"
    @form-submit="handleFormSubmit"
  >
    <template #toolbar-actions>
      <a-button type="primary" @click="tableRef?.openCreateModal()">Add</a-button>
    </template>
  </ProTable>
</template>

Exposed Methods

MethodDescription
refresh()Reload data with current params
reload()Reset pagination and reload
openCreateModal(initialValues?)Open the create modal
openEditModal(record)Open the edit modal (auto-fills data)
vue
<script setup lang="ts">
const tableRef = ref()

// Refresh data
tableRef.value?.refresh()

// Reset and refresh
tableRef.value?.reload()
</script>

<template>
  <ProTable ref="tableRef" :columns="columns" :request="request" />
</template>

ProTableRequest

Type definition for the data fetching function:

typescript
interface ProTableRequest {
  (params: Record<string, any>): Promise<{
    data: any[]      // Data list
    total?: number   // Total count (for pagination)
    success: boolean // Whether the request succeeded
  }>
}

The params object includes pagination info and search form values:

typescript
{
  current: 1,       // Current page
  pageSize: 10,     // Items per page
  name: 'John',     // Search field value
  status: 'active', // Search field value
}

MIT 라이선스에 따라 배포됨