API Reference
fieldsConfig Configuration Details
Complete API for Field Configuration in SmartCrudPage and SmartForm
🎯 Overview
fieldsConfig is the core configuration of NextJS Base, one configuration drives four scenarios: table, form, search, and detail.
📋 Basic Structure
interface FieldConfig {
key: string // Field name (required)
title: string // Display title (required)
type: FieldType // Field type (required)
options?: Option[] | (() => Promise<Option[]>) // Options
table?: TableConfig // Table configuration
form?: FormConfig // Form configuration
search?: SearchConfig // Search configuration
}🔤 Field Types (type)
| Type | Description | Table | Form | Search |
|---|---|---|---|---|
text | Single-line text | ✅ | Input | ✅ |
textarea | Multi-line text | ✅ | TextArea | ✅ |
number | Number | ✅ | InputNumber | ✅ |
select | Dropdown | ✅ | Select | ✅ |
switch | Switch | ✅ | Switch | ✅ |
date | Date | ✅ | DatePicker | ✅ |
datetime | DateTime | ✅ | DateTimePicker | ✅ |
tree-select | Tree Select | ✅ | TreeSelect | ✅ |
icon | Icon | ✅ | IconPicker | ❌ |
image | Single Image | ✅ | ImageUpload | ❌ |
images | Multiple Images | ✅ | MultiImageUpload | ❌ |
markdown | Markdown | ✅ | MarkdownEditor | ❌ |
json | JSON | ✅ | JsonEditor | ❌ |
📊 Table Configuration (table)
interface TableConfig {
// Display Control
width?: number // Column width
fixed?: 'left' | 'right' // Fixed column
hidden?: boolean // Whether to hide
// Text Display
ellipsis?: boolean // Ellipsis for overflow
copyable?: boolean // Copyable
// Sorting
sorter?: boolean // Enable sorting
defaultSortOrder?: 'ascend' | 'descend' // Default sort order
// Custom Render
render?: (value: any, record: any, index: number) => ReactNode
// Value Mapping (for status display)
valueEnum?: Record<string, {
text: string
status?: 'Success' | 'Error' | 'Processing' | 'Warning' | 'Default'
color?: string
}>
}Examples
// Basic Configuration
{
key: 'name',
title: 'Name',
type: 'text',
table: {
width: 200,
ellipsis: true,
copyable: true,
},
}
// Fixed Column
{
key: 'id',
title: 'ID',
type: 'text',
table: {
width: 80,
fixed: 'left',
},
}
// Sorting
{
key: 'createdAt',
title: 'Created At',
type: 'datetime',
table: {
width: 180,
sorter: true,
defaultSortOrder: 'descend',
},
}
// Status Mapping
{
key: 'status',
title: 'Status',
type: 'select',
table: {
width: 100,
valueEnum: {
active: { text: 'Enabled', status: 'Success' },
inactive: { text: 'Disabled', status: 'Error' },
pending: { text: 'Pending', status: 'Processing' },
},
},
}
// Custom Render
{
key: 'price',
title: 'Price',
type: 'number',
table: {
width: 120,
render: (value) => `$${value?.toFixed(2) || '0.00'}`,
},
}
// Hidden Column
{
key: 'remark',
title: 'Remarks',
type: 'textarea',
table: {
hidden: true, // Not displayed in table
},
}📝 Form Configuration (form)
interface FormConfig {
// Display Control
hidden?: boolean // Whether to hide
disabled?: boolean // Whether to disable
readonly?: boolean // Whether read-only
// Validation
required?: boolean // Whether required
rules?: Rule[] // Validation rules
// Default Value
defaultValue?: any
// Input Hints
placeholder?: string
tooltip?: string // Help icon tooltip
extra?: string // Additional description text
// Layout
colSpan?: number // Column width (1-24)
// Field Linkage
dependencies?: string[] // Dependent fields
visible?: (form: FormInstance) => boolean // Dynamic display
fieldProps?: (form: FormInstance) => object // Dynamic properties
// Type-specific Configuration
rows?: number // textarea rows
min?: number // number minimum
max?: number // number maximum
step?: number // number step
precision?: number // number precision
prefix?: string // Prefix
suffix?: string // Suffix
maxCount?: number // Maximum image count
accept?: string // File type
maxSize?: number // File size limit (MB)
}Examples
// Required Text
{
key: 'name',
title: 'Name',
type: 'text',
form: {
required: true,
placeholder: 'Enter name',
rules: [
{ min: 2, message: 'At least 2 characters' },
{ max: 50, message: 'At most 50 characters' },
],
},
}
// Number Input
{
key: 'price',
title: 'Price',
type: 'number',
form: {
required: true,
min: 0,
max: 99999,
precision: 2,
prefix: '$',
placeholder: 'Enter price',
},
}
// Multi-line Text
{
key: 'description',
title: 'Description',
type: 'textarea',
form: {
rows: 4,
maxLength: 500,
showCount: true,
placeholder: 'Enter description',
},
}
// Switch
{
key: 'enable',
title: 'Enabled',
type: 'switch',
form: {
defaultValue: true,
checkedChildren: 'On',
unCheckedChildren: 'Off',
},
}
// Image Upload
{
key: 'avatar',
title: 'Avatar',
type: 'image',
form: {
maxCount: 1,
accept: 'image/*',
maxSize: 2,
tip: 'Supports jpg, png format, max 2MB',
},
}
// Field Linkage
{
key: 'discountType',
title: 'Discount Type',
type: 'select',
options: [
{ label: 'Fixed Amount', value: 'fixed' },
{ label: 'Percentage', value: 'percent' },
],
},
{
key: 'discountValue',
title: 'Discount Value',
type: 'number',
form: {
dependencies: ['discountType'],
fieldProps: (form) => ({
suffix: form.getFieldValue('discountType') === 'percent' ? '%' : '',
max: form.getFieldValue('discountType') === 'percent' ? 100 : undefined,
}),
},
}
// Conditional Display
{
key: 'reason',
title: 'Rejection Reason',
type: 'textarea',
form: {
dependencies: ['status'],
visible: (form) => form.getFieldValue('status') === 'rejected',
required: (form) => form.getFieldValue('status') === 'rejected',
},
}
// Hidden Field
{
key: 'id',
title: 'ID',
type: 'text',
form: {
hidden: true,
},
}🔍 Search Configuration (search)
interface SearchConfig {
enabled?: boolean // Whether to enable search
mode?: 'like' | 'exact' | 'in' | 'range' // Search mode
placeholder?: string // Placeholder
defaultValue?: any // Default value
}Search Mode Details
| Mode | Description | Applicable Types | Prisma Conversion |
|---|---|---|---|
like | Fuzzy Match | text, textarea | { contains: value } |
exact | Exact Match | select, switch, number | value |
in | Multi-select Match | select (multi) | { in: values } |
range | Range Match | date, datetime, number | { gte: start, lte: end } |
Examples
// Fuzzy Search
{
key: 'title',
title: 'Title',
type: 'text',
search: {
enabled: true,
mode: 'like',
placeholder: 'Search title',
},
}
// Exact Match
{
key: 'status',
title: 'Status',
type: 'select',
options: [
{ label: 'Enabled', value: 'active' },
{ label: 'Disabled', value: 'inactive' },
],
search: {
enabled: true,
mode: 'exact',
},
}
// Multi-select Match
{
key: 'tags',
title: 'Tags',
type: 'select',
options: [...],
search: {
enabled: true,
mode: 'in',
},
}
// Date Range
{
key: 'createdAt',
title: 'Created At',
type: 'datetime',
search: {
enabled: true,
mode: 'range',
},
}
// Number Range
{
key: 'price',
title: 'Price',
type: 'number',
search: {
enabled: true,
mode: 'range',
},
}🎨 Options Configuration (options)
Static Options
{
key: 'status',
title: 'Status',
type: 'select',
options: [
{ label: 'Enabled', value: 'active' },
{ label: 'Disabled', value: 'inactive' },
],
}Dynamic Options
{
key: 'categoryId',
title: 'Category',
type: 'select',
options: async () => {
const res = await getCategoryListAction()
return res.data.map(item => ({
label: item.name,
value: item.id,
}))
},
}Tree Options
{
key: 'parentId',
title: 'Parent',
type: 'tree-select',
options: async () => {
const res = await getCategoryTreeAction()
return res.data // Must be tree structure
},
}📚 Complete Example
const fieldsConfig = [
// ID
{
key: 'id',
title: 'ID',
type: 'text',
table: { width: 80, fixed: 'left', copyable: true },
form: { hidden: true },
},
// Name
{
key: 'name',
title: 'Name',
type: 'text',
table: { width: 200, ellipsis: true },
form: { required: true, placeholder: 'Enter name' },
search: { enabled: true, mode: 'like' },
},
// Category
{
key: 'categoryId',
title: 'Category',
type: 'select',
options: async () => {
const res = await getCategoryListAction()
return res.data.map(item => ({ label: item.name, value: item.id }))
},
table: { width: 120 },
form: { required: true },
search: { enabled: true, mode: 'exact' },
},
// Price
{
key: 'price',
title: 'Price',
type: 'number',
table: {
width: 100,
sorter: true,
render: (value) => `$${value?.toFixed(2)}`,
},
form: { required: true, min: 0, precision: 2, prefix: '$' },
search: { enabled: true, mode: 'range' },
},
// Status
{
key: 'enable',
title: 'Status',
type: 'switch',
table: {
width: 80,
render: (value) => value ? '✅ Enabled' : '❌ Disabled',
},
form: { defaultValue: true },
search: { enabled: true, mode: 'exact' },
},
// Remarks
{
key: 'remark',
title: 'Remarks',
type: 'textarea',
table: { hidden: true },
form: { rows: 3 },
},
// Created At
{
key: 'createdAt',
title: 'Created At',
type: 'datetime',
table: { width: 180, sorter: true },
form: { hidden: true },
search: { enabled: true, mode: 'range' },
},
]