Socket
Book a DemoInstallSign in
Socket

antd-crud-table

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

antd-crud-table

`antd-crud-table` is a highly flexible and powerful React library built using `antd` and `@ant-design/pro-components`. It provides both a declarative component-based approach and a modern hook-based architecture for creating editable, paginated tables wit

0.0.14
latest
npmnpm
Version published
Weekly downloads
37
311.11%
Maintainers
1
Weekly downloads
ย 
Created
Source

๐Ÿงฉ antd-crud-table โ€“ A Dynamic React Table Generator with Forms ๐Ÿš€

antd-crud-table is a highly flexible and powerful React library built using antd and @ant-design/pro-components. It provides both a declarative component-based approach and a modern hook-based architecture for creating editable, paginated tables with form support, data fetching, sorting, filtering, and custom rendering. Perfect for building admin dashboards and data management UIs with minimal boilerplate.

๐Ÿ†• Enhanced ๐Ÿ“‹ API Reference

CrudTableExperimental Props (Enhanced)

PropTypeDescription
titlestringTable header title
rowKeykeyof TUnique identifier for each row
columnsCrudColumn<T>[]Column definitions with enhanced features
hookConfigUseCrudTableConfig<T>Hook configuration for data operations
defaultPageSize?numberInitial page size (default: 10)
enableBulkOperations?booleanEnable bulk select/delete (default: false)
customActions?(record, actions) => ReactNode[]Custom row actions

The experimental version introduces a powerful hook-based architecture with multiple data source strategies:

  • Static Data: Perfect for prototypes and small datasets
  • API Integration: REST API support with automatic request handling
  • Custom Operations: Full control with GraphQL, IndexedDB, or custom logic
  • Built-in State Management: Loading states, error handling, optimistic updates

๐Ÿ“ฆ Installation

npm install antd-crud-table

Peer Dependencies:

npm install react react-dom antd @ant-design/pro-components

๐Ÿš€ Quick Start

Choose your preferred approach:

Modern Approach (Experimental) - Hook-Based

import { CrudTableExperimental } from 'antd-crud-table';

// Static data example
const UserManagement = () => (
  <CrudTableExperimental<User>
    title="User Management"
    rowKey="id"
    hookConfig={{
      staticData: users, // Your data array
      optimisticUpdates: true,
    }}
    columns={[
      {
        title: 'Name',
        dataIndex: 'name',
        fieldType: 'string',
        formConfig: { required: true },
      },
      {
        title: 'Status',
        dataIndex: 'status',
        fieldType: 'enum',
        enumOptions: {
          active: { text: 'Active', color: 'green' },
          inactive: { text: 'Inactive', color: 'orange' },
        },
      },
    ]}
  />
);

Classic Approach (Original) - Service-Based

import { CrudTable } from 'antd-crud-table';

const userService = {
  getList: async () => ({ data: [], total: 0 }),
  create: async (data) => data,
  update: async (id, data) => data,
  delete: async (id) => {},
};

const UserTable = () => (
  <CrudTable
    title="User Management"
    rowKey="id"
    service={userService}
    columns={[
      {
        title: 'Name',
        dataIndex: 'name',
        fieldType: 'string',
        fieldEditable: true,
        formConfig: { required: true },
      },
    ]}
  />
);

๐ŸŽฏ Enhanced Features (Experimental)

1. Multiple Data Source Strategies

Static Data (Perfect for Prototyping)

<CrudTableExperimental
  hookConfig={{
    staticData: mockUsers,
    optimisticUpdates: true,
  }}
  // ... other props
/>

API Integration (Production Ready)

<CrudTableExperimental
  hookConfig={{
    api: {
      baseUrl: 'https://api.example.com',
      endpoints: {
        list: '/users',
        create: '/users', 
        update: '/users',
        delete: '/users',
      },
      headers: {
        'Authorization': 'Bearer your-token',
      },
      transform: {
        response: (data) => ({
          data: data.users,
          total: data.totalCount,
        }),
        request: (data) => ({
          ...data,
          updatedAt: new Date().toISOString(),
        }),
      },
    },
    onSuccess: (operation, data) => {
      console.log(`${operation} completed`, data);
    },
    onError: (operation, error) => {
      console.error(`${operation} failed`, error);
    },
  }}
  // ... other props
/>

Custom Operations (Maximum Flexibility)

<CrudTableExperimental
  hookConfig={{
    operations: {
      getList: async (params) => {
        const result = await myGraphQLQuery(params);
        return {
          data: result.users,
          total: result.totalCount,
          success: true,
        };
      },
      create: async (data) => await myCreateMutation(data),
      update: async (id, data) => await myUpdateMutation(id, data),
      delete: async (id) => await myDeleteMutation(id),
    },
  }}
  // ... other props
/>

2. Advanced Features

Bulk Operations

<CrudTableExperimental
  enableBulkOperations={true}
  // Automatically adds bulk select and delete functionality
/>

Custom Actions

<CrudTableExperimental
  customActions={(record, actions) => [
    <Button
      key="export"
      onClick={() => exportUser(record)}
    >
      Export
    </Button>,
    <Button
      key="clone"
      onClick={() => actions.create({...record, id: undefined})}
    >
      Clone
    </Button>
  ]}
/>

Enhanced Validation

columns={[
  {
    dataIndex: 'email',
    title: 'Email',
    fieldType: 'string',
    formConfig: {
      required: true,
      rules: [
        { required: true, message: 'Email is required' },
        { type: 'email', message: 'Invalid email format' },
        { 
          validator: async (_, value) => {
            const exists = await checkEmailExists(value);
            if (exists) throw new Error('Email already exists');
          }
        }
      ],
    },
  },
]}

3. Custom Hooks

Create your own specialized hooks for different use cases:

Example 1: useUserCrud - Specialized User Management

import { useCrudTable, type UseCrudTableConfig } from 'antd-crud-table';

#### Example 1: useUserCrud - Specialized User Management
```tsx
import { useCrudTable, type UseCrudTableConfig } from 'antd-crud-table';

export const useUserCrud = (baseConfig?: Partial<UseCrudTableConfig<any>['api']>) => {
  const config: UseCrudTableConfig<any> = {
    api: {
      baseUrl: '/api/users',
      headers: {
        'Authorization': `Bearer ${localStorage.getItem('token')}`,
      },
      transform: {
        request: (data) => ({
          ...data,
          // Add default values or transformations
          updatedAt: new Date().toISOString(),
        }),
        response: (data) => ({
          data: data.users || data.data || [],
          total: data.total || data.count || 0,
          success: true,
        }),
      },
      ...baseConfig,
    },
    defaultPageSize: 10,
    optimisticUpdates: true,
    onSuccess: (operation, data) => {
      console.log(`User ${operation} completed:`, data);
    },
    onError: (operation, error) => {
      console.error(`User ${operation} failed:`, error);
      // Could add toast notifications, error reporting, etc.
    },
  };

  return useCrudTable('id', config);
};

Example 2: useLocalStorageCrud - Local Storage Persistence

export const useLocalStorageCrud = <T extends Record<string, any>>(
  storageKey: string,
  rowKey: keyof T,
  initialData: T[] = []
) => {
  const getStoredData = (): T[] => {
    try {
      const stored = localStorage.getItem(storageKey);
      return stored ? JSON.parse(stored) : initialData;
    } catch {
      return initialData;
    }
  };

  const setStoredData = (data: T[]) => {
    localStorage.setItem(storageKey, JSON.stringify(data));
  };

  return useCrudTable(rowKey, {
    operations: {
      getList: async (params) => {
        const data = getStoredData();
        const { current = 1, pageSize = 10, ...filters } = params;
        
        // Apply filters
        let filteredData = data;
        Object.entries(filters).forEach(([key, value]) => {
          if (value !== undefined && value !== null && value !== '') {
            filteredData = filteredData.filter(item =>
              String(item[key]).toLowerCase().includes(String(value).toLowerCase())
            );
          }
        });
        
        // Apply pagination
        const start = (current - 1) * pageSize;
        const paginatedData = filteredData.slice(start, start + pageSize);
        
        return {
          data: paginatedData,
          total: filteredData.length,
          success: true,
        };
      },
      
      create: async (newItem) => {
        const data = getStoredData();
        const maxId = Math.max(...data.map(item => Number(item[rowKey]) || 0), 0);
        const created = { 
          [rowKey]: maxId + 1, 
          ...newItem,
          createdAt: new Date().toISOString(),
        } as T;
        
        data.push(created);
        setStoredData(data);
        return created;
      },
      
      update: async (id, updateData) => {
        const data = getStoredData();
        const index = data.findIndex(item => item[rowKey] === id);
        if (index === -1) throw new Error('Item not found');
        
        data[index] = { 
          ...data[index], 
          ...updateData,
          updatedAt: new Date().toISOString(),
        };
        setStoredData(data);
        return data[index];
      },
      
      delete: async (id) => {
        const data = getStoredData();
        const filtered = data.filter(item => item[rowKey] !== id);
        setStoredData(filtered);
      },
    },
    optimisticUpdates: true,
  });
};

Example 3: useRealtimeCrud - WebSocket Integration

#### Example 3: useRealtimeCrud - WebSocket Integration
```tsx
export const useRealtimeCrud = <T extends Record<string, any>>(
  rowKey: keyof T,
  websocketUrl: string,
  apiConfig: UseCrudTableConfig<T>['api']
) => {
  const config: UseCrudTableConfig<T> = {
    api: apiConfig,
    optimisticUpdates: false, // Disable optimistic updates for realtime
  };
  
  const crud = useCrudTable(rowKey, config);

  // In a real implementation, you would set up WebSocket listeners here
  // useEffect(() => {
  //   const ws = new WebSocket(websocketUrl);
  //   
  //   ws.onmessage = (event) => {
  //     const { type, data } = JSON.parse(event.data);
  //     switch (type) {
  //       case 'created':
  //       case 'updated':
  //       case 'deleted':
  //         crud.refresh(); // Refresh data when changes occur
  //         break;
  //     }
  //   };
  //   
  //   return () => ws.close();
  // }, [websocketUrl]);

  return crud;
};

Example 4: useInfiniteScrollCrud - Infinite Scrolling

#### Example 4: useInfiniteScrollCrud - Infinite Scrolling
```tsx
export const useInfiniteScrollCrud = <T extends Record<string, any>>(
  rowKey: keyof T,
  baseConfig: UseCrudTableConfig<T>
) => {
  // This would extend the base hook with infinite scroll capabilities
  // Implementation would handle cursor-based pagination, data accumulation, etc.
  
  const config: UseCrudTableConfig<T> = {
    ...baseConfig,
    // Add infinite scroll specific configuration
  };
  
  return useCrudTable(rowKey, config);
};

Example 5: useCachedCrud - Advanced Caching

#### Example 5: useCachedCrud - Advanced Caching
```tsx
export const useCachedCrud = <T extends Record<string, any>>(
  rowKey: keyof T,
  cacheKey: string,
  baseConfig: UseCrudTableConfig<T>
) => {
  const config: UseCrudTableConfig<T> = {
    ...baseConfig,
    enableCache: true,
    // In a real implementation, you might integrate with:
    // - React Query
    // - SWR  
    // - Redux Toolkit Query
    // - Apollo Client
    // etc.
  };
  
  return useCrudTable(rowKey, config);
};
};

Usage Examples

// Using the specialized hooks
const UserTable = () => {
  const userCrud = useUserCrud();
  
  return (
    <CrudTableExperimental
      title="Users" 
      rowKey="id"
      hookConfig={userCrud}
      columns={userColumns}
    />
  );
};

const OfflineTable = () => {
  const offlineCrud = useLocalStorageCrud<User>('users-cache', 'id', mockUsers);
  
  return (
    <CrudTableExperimental
      title="Offline Users" 
      rowKey="id"
      hookConfig={offlineCrud}
      columns={userColumns}
    />
  );
};

const RealtimeTable = () => {
  const realtimeCrud = useRealtimeCrud<User>(
    'id',
    'wss://api.example.com/ws',
    { baseUrl: '/api/users' }
  );
  
  return (
    <CrudTableExperimental
      title="Realtime Users" 
      rowKey="id"
      hookConfig={realtimeCrud}
      columns={userColumns}
    />
  );
};

๐Ÿ† Complete Feature Set

Core Features

  • ๐ŸŽจ Multiple Column Types: string, number, boolean, date, enum, custom
  • โœ… Integrated Create/Edit Modal Forms with validation
  • ๐Ÿš€ ProTable Integration: Sorting, pagination & filtering built-in
  • ๐Ÿ” Real-time Data Operations with loading states
  • ๐Ÿง  Custom Transform & Render Logic per field
  • ๐Ÿ“† Smart Date/Time Handling with date-fns + dayjs
  • ๐Ÿงฐ Full TypeScript Support with generics
  • ๐Ÿ” Field-Level Edit Controls
  • ๐Ÿงผ Professional UI with row differentiation

Enhanced Features (Experimental)

  • ๐Ÿช Hook-Based Architecture with useCrudTable
  • ๐Ÿ”Œ Multiple Data Sources: Static, API, or custom operations
  • โšก Built-in State Management: Loading, error states, optimistic updates
  • ๐Ÿ”ง Extensible Design: Create custom hooks for your domain
  • ๐Ÿ“Š Performance Optimized: Caching, lazy loading, optimistic updates
  • ๐ŸŽ›๏ธ Bulk Operations: Select and delete multiple rows
  • ๐ŸŽฏ Custom Actions: Add your own row-level actions
  • ๐Ÿ” Advanced Search: Configurable column-level search
  • โœจ Enhanced Validation: Complex form validation rules

API Reference

CrudTableV2 Props (Enhanced)

PropTypeDescription
titlestringTable header title
rowKeykeyof TUnique identifier for each row
columnsCrudColumn<T>[]Column definitions with enhanced features
hookConfigUseCrudTableConfig<T>Hook configuration for data operations
defaultPageSize?numberInitial page size (default: 10)
enableBulkOperations?booleanEnable bulk select/delete (default: false)
customActions?(record, actions) => ReactNode[]Custom row actions

CrudColumn (Enhanced)

PropTypeDescription
dataIndexkeyof TField key in your data
titlestringColumn header text
fieldTypeFieldType"string" | "number" | "boolean" | "date" | "enum" | "custom"
fieldEditable?booleanWhether field can be edited (default: true)
searchable?booleanWhether field appears in search (default: true)
enumOptions?Record<string, {text: string, color?: string}>Options for enum fields
customRender?(value, record) => ReactNodeCustom display renderer
formConfig?FormConfigForm field configuration

FormConfig

PropTypeDescription
required?booleanWhether field is required
rules?FormRule[]Ant Design validation rules
component?ReactNodeCustom form component
transform?(value) => anyTransform value before saving

UseCrudTableConfig

Choose one approach:

// Static data approach
{
  staticData: T[];
  optimisticUpdates?: boolean;
}

// API approach  
{
  api: {
    baseUrl: string;
    endpoints?: {...};
    headers?: Record<string, string>;
    transform?: {...};
  };
}

// Custom operations approach
{
  operations: {
    getList: (params) => Promise<{data: T[], total: number}>;
    create: (data: Partial<T>) => Promise<T>;
    update: (id, data: Partial<T>) => Promise<T>;
    delete: (id) => Promise<void>;
  };
}

Legacy CrudTable Props (Original)

PropTypeDescription
columnsCrudColumn<T>[]Column definitions
serviceCrudService<T>Service object with CRUD methods
rowKeykeyof TUnique key for each row
titlestringTable header title
defaultPageSize?numberOptional default page size (default: 5)

๐Ÿ“ Styling

Customize row striping using .row-differentiator in CrudTable.css:

.row-differentiator {
  background-color: #fafafa;
}

๐Ÿ“Œ Notes

  • Date fields are handled via dayjs in the form and date-fns for display.
  • All requests are async with error handling via antd's message API.
  • Add your own export logic or additional toolbar buttons as needed.

๐Ÿ”„ Migration Guide

Upgrading from Original to Experimental

Original (Service-Based):

<CrudTable
  title="Users"
  rowKey="id"
  service={UserService}
  columns={columns}
/>

Experimental (Hook-Based):

<CrudTableExperimental
  title="Users" 
  rowKey="id"
  hookConfig={{
    operations: UserService, // Reuse existing service
    // Or choose new approaches:
    // staticData: users,
    // api: { baseUrl: '/api' },
  }}
  columns={columns}
/>

Breaking Changes in Experimental

  • โœ… Fully backward compatible: Original components still work
  • ๐Ÿ”„ New import: CrudTableExperimental for enhanced version
  • ๐ŸŽ›๏ธ Service โ†’ hookConfig: More flexible configuration
  • ๐Ÿ“Š Enhanced props: Additional optional features

Lazy Loading Options

For better performance with code splitting:

// Standard lazy loading
import { CrudTableLazy } from 'antd-crud-table';

// Experimental lazy loading  
import { CrudTableExperimentalLazy } from 'antd-crud-table';

<CrudTableExperimentalLazy
  title="Users"
  rowKey="id" 
  hookConfig={hookConfig}
  columns={columns}
/>

๐ŸŽจ Column Type Examples

String Field

{
  dataIndex: 'name',
  title: 'Full Name',
  fieldType: 'string',
  formConfig: {
    required: true,
    rules: [
      { min: 2, message: 'Name must be at least 2 characters' }
    ]
  },
}

Number Field

{
  dataIndex: 'age',
  title: 'Age',
  fieldType: 'number',
  formConfig: {
    rules: [
      { type: 'number', min: 0, max: 120, message: 'Invalid age' }
    ]
  },
}

Date Field

{
  dataIndex: 'createdAt',
  title: 'Created Date',
  fieldType: 'date',
  searchable: false, // Exclude from search
}

Boolean Field

{
  dataIndex: 'isActive',
  title: 'Active Status',
  fieldType: 'boolean',
}

Enum Field

{
  dataIndex: 'status',
  title: 'Status',
  fieldType: 'enum',
  enumOptions: {
    active: { text: 'Active', color: 'green' },
    pending: { text: 'Pending', color: 'orange' },
    inactive: { text: 'Inactive', color: 'red' },
  },
}

Custom Field

{
  dataIndex: 'customField',
  title: 'Custom Display',
  fieldType: 'custom',
  customRender: (value, record) => (
    <div>
      <Avatar src={record.avatar} />
      <span>{record.name}</span>
    </div>
  ),
  formConfig: {
    component: <MyCustomInput />,
  },
}

๐Ÿงช Testing

The hook-based architecture enables easy testing:

import { renderHook, act } from '@testing-library/react';
import { useCrudTable } from 'antd-crud-table';

test('should handle CRUD operations', async () => {
  const mockData = [
    { id: 1, name: 'John', age: 30 }
  ];

  const { result } = renderHook(() => 
    useCrudTable('id', {
      staticData: mockData,
    })
  );

  await act(async () => {
    const created = await result.current.create({ 
      name: 'Jane', 
      age: 25 
    });
    expect(created).toBeTruthy();
  });

  expect(result.current.state.data).toHaveLength(2);
});

๐Ÿš€ Performance Tips

1. Use Static Data for Prototyping

// Perfect for demos and development
hookConfig={{ staticData: mockData }}

2. Enable Optimistic Updates

// For better UX with reliable backends
hookConfig={{ 
  api: {...},
  optimisticUpdates: true 
}}

3. Implement Proper Caching

// Custom hook with caching
const useUserCrud = () => {
  return useCrudTable('id', {
    enableCache: true,
    // ... other config
  });
};

4. Lazy Load Components

import { CrudTableLazy } from 'antd-crud-table';
// Component will be loaded when needed

๐Ÿ”ฎ Roadmap

Coming Soon

  • ๐ŸŒ WebSocket Integration: Real-time updates
  • ๐Ÿ“Š Virtual Scrolling: Handle thousands of rows
  • ๐Ÿ“ค Export Functionality: CSV/Excel export
  • ๐ŸŽจ Theme Support: Multiple UI themes
  • ๐Ÿ” Advanced Filters: Complex filtering UI
  • ๐Ÿ“ฑ Mobile Optimization: Better mobile experience

Community Requests

  • ๐Ÿ”ง Plugin System: Extensible architecture
  • ๐Ÿ“ˆ Analytics Integration: Built-in tracking
  • ๐ŸŒ i18n Support: Multi-language support

๐Ÿค Contributing

We welcome contributions! Please see our Contributing Guide.

Development Setup

git clone https://github.com/maifeeulasad/antd-crud-table
cd antd-crud-table
npm install
npm run dev

๐Ÿ“„ License

MIT License - feel free to use in personal and commercial projects.

๐ŸŽ‰ Build elegant CRUD interfaces faster than ever with antd-crud-table!

References

Keywords

antd

FAQs

Package last updated on 10 Aug 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

About

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.

  • Terms
  • Privacy
  • Security

Made with โšก๏ธ by Socket Inc

U.S. Patent No. 12,346,443 & 12,314,394. Other pending.