|
1 | 1 | --- |
2 | 2 | title: "ObjectTable" |
| 3 | +description: "Unified table component with ObjectQL integration, built on data-table foundation" |
3 | 4 | --- |
4 | 5 |
|
5 | 6 | import { InteractiveDemo } from '@/app/components/InteractiveDemo'; |
| 7 | +import { ComponentDemo } from '@/app/components/ComponentDemo'; |
6 | 8 |
|
7 | | -A specialized table component that automatically fetches and displays data from ObjectQL objects with sorting, filtering, and pagination. |
| 9 | +A specialized table component that automatically fetches and displays data from ObjectQL objects. Built on the data-table foundation, it combines ObjectQL schema integration with enterprise-grade table features. |
| 10 | + |
| 11 | +## Overview |
| 12 | + |
| 13 | +ObjectTable supports two modes: |
| 14 | +- **Table Mode** (`type: 'object-table'`): Traditional CRUD operations with auto-generated columns |
| 15 | +- **Grid Mode** (`type: 'object-grid'`): Spreadsheet-like inline editing with keyboard navigation |
| 16 | + |
| 17 | +Both modes inherit all data-table features: sorting, filtering, pagination, row selection, CSV export, column resizing, and reordering. |
8 | 18 |
|
9 | 19 | ## Interactive Demo |
10 | 20 |
|
11 | 21 | <InteractiveDemo |
12 | 22 | schema={{ |
13 | 23 | type: "object-table", |
14 | 24 | objectName: "users", |
15 | | - columns: [ |
16 | | - { header: "Name", accessorKey: "name" }, |
17 | | - { header: "Email", accessorKey: "email" }, |
18 | | - { header: "Role", accessorKey: "role" }, |
19 | | - { header: "Status", accessorKey: "status" } |
20 | | - ], |
| 25 | + title: "User Management", |
| 26 | + fields: ["name", "email", "role", "status"], |
21 | 27 | data: [ |
22 | 28 | { id: 1, name: "Alice Johnson", email: "alice@example.com", role: "Admin", status: "Active" }, |
23 | 29 | { id: 2, name: "Bob Smith", email: "bob@example.com", role: "User", status: "Active" }, |
24 | | - { id: 3, name: "Carol White", email: "carol@example.com", role: "User", status: "Inactive" } |
| 30 | + { id: 3, name: "Carol White", email: "carol@example.com", role: "Manager", status: "Inactive" }, |
| 31 | + { id: 4, name: "David Brown", email: "david@example.com", role: "User", status: "Active" } |
25 | 32 | ], |
26 | 33 | pageSize: 10, |
27 | | - searchable: true, |
28 | | - selectable: true |
| 34 | + showSearch: true, |
| 35 | + selectable: "multiple", |
| 36 | + operations: { |
| 37 | + update: true, |
| 38 | + delete: true, |
| 39 | + export: true |
| 40 | + } |
29 | 41 | }} |
30 | | - title="ObjectTable Component" |
31 | | - description="Auto-generated table with sorting, filtering, and pagination" |
| 42 | + title="ObjectTable - Table Mode" |
| 43 | + description="Auto-generated columns with type-aware rendering and CRUD operations" |
32 | 44 | /> |
33 | 45 |
|
34 | | -## Basic Usage |
| 46 | +## Table Mode - Basic Usage |
35 | 47 |
|
36 | 48 | ```tsx |
37 | 49 | import { ObjectTable } from '@object-ui/plugin-object'; |
38 | | -import { ObjectQLDataSource } from '@object-ui/data-objectql'; |
39 | | - |
40 | | -const dataSource = new ObjectQLDataSource({ |
41 | | - baseUrl: 'https://api.example.com', |
42 | | - token: 'your-auth-token' |
43 | | -}); |
44 | 50 |
|
45 | 51 | function UsersTable() { |
46 | 52 | return ( |
47 | 53 | <ObjectTable |
48 | 54 | schema={{ |
49 | 55 | type: 'object-table', |
50 | 56 | objectName: 'users', |
51 | | - columns: ['name', 'email', 'status', 'created_at'] |
| 57 | + fields: ['name', 'email', 'status', 'created_at'], |
| 58 | + operations: { |
| 59 | + create: true, |
| 60 | + update: true, |
| 61 | + delete: true |
| 62 | + }, |
| 63 | + showSearch: true, |
| 64 | + showPagination: true, |
| 65 | + pageSize: 25 |
52 | 66 | }} |
53 | 67 | dataSource={dataSource} |
| 68 | + onEdit={(record) => console.log('Edit:', record)} |
| 69 | + onDelete={(record) => console.log('Delete:', record)} |
54 | 70 | /> |
55 | 71 | ); |
56 | 72 | } |
57 | 73 | ``` |
58 | 74 |
|
59 | | -## JSON Schema |
60 | | - |
61 | | -```json |
62 | | -{ |
63 | | - "type": "object-table", |
64 | | - "objectName": "users", |
65 | | - "columns": ["name", "email", "status"], |
66 | | - "filters": { |
67 | | - "status": "active" |
68 | | - }, |
69 | | - "pageSize": 20, |
70 | | - "sortBy": "created_at", |
71 | | - "sortOrder": "desc" |
| 75 | +## Grid Mode - Inline Editing |
| 76 | + |
| 77 | +```tsx |
| 78 | +function InventoryGrid() { |
| 79 | + return ( |
| 80 | + <ObjectTable |
| 81 | + schema={{ |
| 82 | + type: 'object-grid', |
| 83 | + objectName: 'inventory', |
| 84 | + fields: ['sku', 'name', 'quantity', 'price', 'status'], |
| 85 | + editable: true, |
| 86 | + keyboardNavigation: true, |
| 87 | + frozenColumns: 2, |
| 88 | + resizableColumns: true |
| 89 | + }} |
| 90 | + dataSource={dataSource} |
| 91 | + onCellChange={(row, col, value) => { |
| 92 | + console.log(`Updated: Row ${row}, Column ${col}:`, value); |
| 93 | + }} |
| 94 | + /> |
| 95 | + ); |
72 | 96 | } |
73 | 97 | ``` |
74 | 98 |
|
75 | | -## Properties |
| 99 | +## Features from data-table |
| 100 | + |
| 101 | +All ObjectTable instances automatically include: |
| 102 | + |
| 103 | +✅ **Multi-column sorting** - Click headers to sort (ascending/descending/none) |
| 104 | +✅ **Real-time search** - Search across all visible columns |
| 105 | +✅ **Pagination** - Navigate large datasets efficiently |
| 106 | +✅ **Row selection** - Single or multiple selection with callbacks |
| 107 | +✅ **CSV export** - Export filtered and sorted data |
| 108 | +✅ **Column resizing** - Drag column borders to resize |
| 109 | +✅ **Column reordering** - Drag column headers to reorder |
| 110 | + |
| 111 | +## Field Type Rendering |
| 112 | + |
| 113 | +ObjectTable automatically uses specialized renderers based on field types: |
| 114 | + |
| 115 | +- **Text**: text, textarea, markdown, html |
| 116 | +- **Numeric**: number, currency, percent |
| 117 | +- **Boolean**: checkmarks with color coding |
| 118 | +- **Date/Time**: date, datetime, time with locale formatting |
| 119 | +- **Selection**: select, multi-select with colored badges |
| 120 | +- **Contact**: email (mailto links), phone (tel links), url (external links) |
| 121 | +- **Files**: file, image with thumbnails |
| 122 | +- **Relationships**: lookup, master-detail |
| 123 | +- **Computed**: formula, summary (read-only) |
| 124 | +- **User**: user, owner with avatars |
| 125 | + |
| 126 | +## Schema Properties |
| 127 | + |
| 128 | +### Common Properties |
76 | 129 |
|
77 | 130 | | Property | Type | Default | Description | |
78 | 131 | |----------|------|---------|-------------| |
| 132 | +| `type` | `'object-table'` \| `'object-grid'` | Required | Component mode | |
79 | 133 | | `objectName` | string | Required | Name of the ObjectQL object | |
80 | | -| `columns` | string[] | All fields | Columns to display | |
81 | | -| `filters` | object | `{}` | Default filters to apply | |
| 134 | +| `fields` | string[] | All fields | Fields to display as columns | |
| 135 | +| `data` | any[] | - | Inline data (optional) | |
82 | 136 | | `pageSize` | number | `10` | Rows per page | |
83 | | -| `sortBy` | string | `'id'` | Default sort field | |
84 | | -| `sortOrder` | 'asc' \| 'desc' | `'asc'` | Default sort order | |
85 | | -| `selectable` | boolean | `false` | Enable row selection | |
86 | | -| `searchable` | boolean | `true` | Enable search bar | |
87 | | - |
88 | | -## Features |
89 | | - |
90 | | -- **Automatic Data Fetching**: Connects to ObjectQL backend and fetches data automatically |
91 | | -- **Sorting**: Click column headers to sort data |
92 | | -- **Filtering**: Apply filters to narrow down results |
93 | | -- **Pagination**: Navigate through large datasets efficiently |
94 | | -- **Search**: Full-text search across all columns |
95 | | -- **Selection**: Select single or multiple rows |
96 | | -- **Responsive**: Adapts to different screen sizes |
97 | | - |
98 | | -## Example: User Management Dashboard |
99 | | - |
100 | | -```json |
101 | | -{ |
102 | | - "type": "page", |
103 | | - "title": "User Management", |
104 | | - "body": [ |
105 | | - { |
106 | | - "type": "card", |
107 | | - "title": "Users", |
108 | | - "className": "p-6", |
109 | | - "children": { |
110 | | - "type": "object-table", |
111 | | - "objectName": "users", |
112 | | - "columns": ["name", "email", "role", "status", "last_login"], |
113 | | - "searchable": true, |
114 | | - "selectable": true, |
115 | | - "actions": [ |
116 | | - { |
117 | | - "type": "button", |
118 | | - "label": "New User", |
119 | | - "variant": "default", |
120 | | - "action": { |
121 | | - "type": "navigate", |
122 | | - "path": "/users/new" |
123 | | - } |
124 | | - } |
125 | | - ] |
126 | | - } |
127 | | - } |
128 | | - ] |
129 | | -} |
130 | | -``` |
| 137 | +| `selectable` | boolean \| `'single'` \| `'multiple'` | `false` | Row selection mode | |
131 | 138 |
|
132 | | -## Advanced Configuration |
133 | | - |
134 | | -### Custom Column Display |
135 | | - |
136 | | -You can customize how columns are displayed using the column configuration: |
137 | | - |
138 | | -```json |
139 | | -{ |
140 | | - "type": "object-table", |
141 | | - "objectName": "products", |
142 | | - "columns": [ |
143 | | - { |
144 | | - "field": "name", |
145 | | - "header": "Product Name", |
146 | | - "width": 200 |
147 | | - }, |
148 | | - { |
149 | | - "field": "price", |
150 | | - "header": "Price", |
151 | | - "format": "currency" |
152 | | - }, |
153 | | - { |
154 | | - "field": "status", |
155 | | - "header": "Status", |
156 | | - "badge": true |
157 | | - } |
158 | | - ] |
159 | | -} |
160 | | -``` |
| 139 | +### Table Mode Properties |
161 | 140 |
|
162 | | -### Pre-filtering Data |
| 141 | +| Property | Type | Description | |
| 142 | +|----------|------|-------------| |
| 143 | +| `operations` | object | Enable CRUD operations | |
| 144 | +| `showSearch` | boolean | Show search box | |
| 145 | +| `showPagination` | boolean | Show pagination | |
| 146 | +| `defaultSort` | object | Default sorting | |
163 | 147 |
|
164 | | -Apply default filters that users can modify: |
| 148 | +### Grid Mode Properties |
165 | 149 |
|
166 | | -```json |
167 | | -{ |
168 | | - "type": "object-table", |
169 | | - "objectName": "orders", |
170 | | - "columns": ["order_number", "customer", "total", "status"], |
171 | | - "filters": { |
172 | | - "status": ["pending", "processing"], |
173 | | - "created_at": { |
174 | | - "gte": "2024-01-01" |
175 | | - } |
176 | | - } |
177 | | -} |
| 150 | +| Property | Type | Description | |
| 151 | +|----------|------|-------------| |
| 152 | +| `editable` | boolean | Enable inline cell editing | |
| 153 | +| `keyboardNavigation` | boolean | Arrow keys, Tab, Enter navigation | |
| 154 | +| `frozenColumns` | number | Number of left-pinned columns | |
| 155 | +| `resizableColumns` | boolean | Enable column resizing | |
| 156 | + |
| 157 | +## Keyboard Shortcuts (Grid Mode) |
| 158 | + |
| 159 | +| Shortcut | Action | |
| 160 | +|----------|--------| |
| 161 | +| `↑` `↓` `←` `→` | Navigate between cells | |
| 162 | +| `Tab` | Move to next cell | |
| 163 | +| `Shift + Tab` | Move to previous cell | |
| 164 | +| `Enter` | Start editing selected cell | |
| 165 | +| `Escape` | Cancel editing | |
| 166 | + |
| 167 | +## Migration from ObjectGrid |
| 168 | + |
| 169 | +ObjectGrid has been merged into ObjectTable: |
| 170 | + |
| 171 | +**Before:** |
| 172 | +```tsx |
| 173 | +import { ObjectGrid } from '@object-ui/plugin-object'; |
| 174 | +<ObjectGrid schema={{ type: 'object-grid', ... }} /> |
| 175 | +``` |
| 176 | + |
| 177 | +**After:** |
| 178 | +```tsx |
| 179 | +import { ObjectTable } from '@object-ui/plugin-object'; |
| 180 | +<ObjectTable schema={{ type: 'object-grid', ... }} /> |
178 | 181 | ``` |
179 | 182 |
|
180 | 183 | ## Related Components |
181 | 184 |
|
182 | 185 | - [ObjectForm](/docs/plugins/plugin-object/object-form) - Create and edit records |
183 | 186 | - [ObjectView](/docs/plugins/plugin-object/object-view) - Complete CRUD interface |
| 187 | +- [Data Table](/docs/components/complex/data-table) - Base table component |
0 commit comments