ng-dynamic-datatable 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +437 -89
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,114 +1,343 @@
|
|
|
1
|
-
# dynamic-datatable
|
|
1
|
+
# ng-dynamic-datatable
|
|
2
2
|
|
|
3
|
-
Config-driven Angular DataTable library
|
|
3
|
+
Config-driven Angular DataTable library for rendering reusable tables from JSON data and column definitions.
|
|
4
|
+
|
|
5
|
+
The package is designed for Angular standalone applications and supports sorting, searching, pagination, selection, actions, and export.
|
|
4
6
|
|
|
5
7
|
## Features
|
|
6
8
|
|
|
7
|
-
- Dynamic columns
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
9
|
+
- Dynamic columns from config
|
|
10
|
+
- JSON data input
|
|
11
|
+
- Column sorting
|
|
12
|
+
- Global search across visible columns
|
|
13
|
+
- Pagination
|
|
14
|
+
- Rows per page selector
|
|
15
|
+
- Checkbox row selection
|
|
16
|
+
- Row action menu
|
|
17
|
+
- CSV export
|
|
18
|
+
- Excel export
|
|
19
|
+
- Custom cell rendering with HTML strings
|
|
20
|
+
|
|
21
|
+
## Package Name
|
|
22
|
+
|
|
23
|
+
Install the published package with:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install ng-dynamic-datatable
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Do not use `dynamic-datatable`. The published npm package name is `ng-dynamic-datatable`.
|
|
30
|
+
|
|
31
|
+
## Requirements
|
|
32
|
+
|
|
33
|
+
- Angular 19.x
|
|
34
|
+
- `@angular/common` and `@angular/core` compatible with `^19.2.0`
|
|
35
|
+
- `bootstrap` is recommended for layout consistency
|
|
36
|
+
- `bootstrap-icons` is recommended if you use action icons like `bi bi-eye`
|
|
14
37
|
|
|
15
|
-
## Install
|
|
38
|
+
## Install In Your Angular App
|
|
16
39
|
|
|
17
40
|
```bash
|
|
18
|
-
npm install dynamic-datatable
|
|
41
|
+
npm install ng-dynamic-datatable
|
|
42
|
+
npm install bootstrap bootstrap-icons
|
|
19
43
|
```
|
|
20
44
|
|
|
21
|
-
|
|
45
|
+
Add Bootstrap styles in your Angular app configuration.
|
|
22
46
|
|
|
23
|
-
|
|
47
|
+
Example `angular.json` styles section:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"styles": [
|
|
52
|
+
"node_modules/bootstrap/dist/css/bootstrap.min.css",
|
|
53
|
+
"node_modules/bootstrap-icons/font/bootstrap-icons.css",
|
|
54
|
+
"src/styles.css"
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Quick Start
|
|
60
|
+
|
|
61
|
+
Import the standalone component directly into your Angular component.
|
|
24
62
|
|
|
25
63
|
```ts
|
|
26
64
|
import { Component } from '@angular/core';
|
|
27
65
|
import {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
66
|
+
DynamicDatatableComponent,
|
|
67
|
+
DynamicDataTableConfig,
|
|
68
|
+
DataTableColumn,
|
|
69
|
+
DataTableActionEvent
|
|
31
70
|
} from 'ng-dynamic-datatable';
|
|
32
71
|
|
|
33
72
|
@Component({
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
73
|
+
selector: 'app-users',
|
|
74
|
+
standalone: true,
|
|
75
|
+
imports: [DynamicDatatableComponent],
|
|
76
|
+
template: `
|
|
77
|
+
<lib-dynamic-datatable
|
|
78
|
+
[config]="config"
|
|
79
|
+
[columns]="columns"
|
|
80
|
+
[data]="rows"
|
|
81
|
+
(actionSelected)="onAction($event)"
|
|
82
|
+
(selectionChange)="onSelection($event)"
|
|
83
|
+
(sortChange)="onSort($event)"
|
|
84
|
+
(pageChange)="onPage($event)"
|
|
85
|
+
(exportTriggered)="onExport($event)"
|
|
86
|
+
></lib-dynamic-datatable>
|
|
87
|
+
`
|
|
46
88
|
})
|
|
47
89
|
export class UsersComponent {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
rows = [
|
|
91
|
+
{
|
|
92
|
+
id: 1,
|
|
93
|
+
initials: 'AS',
|
|
94
|
+
name: 'Aarav Sharma',
|
|
95
|
+
designation: 'Tax Accountant',
|
|
96
|
+
email: 'aarav.sharma@company.in',
|
|
97
|
+
salary: '19366.53',
|
|
98
|
+
status: 'Resigned'
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
id: 2,
|
|
102
|
+
initials: 'AP',
|
|
103
|
+
name: 'Ananya Patel',
|
|
104
|
+
designation: 'Staff Accountant',
|
|
105
|
+
email: 'ananya.patel@company.in',
|
|
106
|
+
salary: '10745.32',
|
|
107
|
+
status: 'Applied'
|
|
108
|
+
}
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
columns: DataTableColumn[] = [
|
|
112
|
+
{
|
|
113
|
+
key: 'name',
|
|
114
|
+
label: 'Name',
|
|
115
|
+
sortable: true,
|
|
116
|
+
width: '240px',
|
|
117
|
+
render: (row) => `
|
|
118
|
+
<div class="demo-user">
|
|
119
|
+
<div class="demo-avatar">${String(row['initials'] ?? '')}</div>
|
|
120
|
+
<div>
|
|
121
|
+
<div class="demo-name">${String(row['name'] ?? '')}</div>
|
|
122
|
+
<div class="demo-subtitle">${String(row['designation'] ?? '')}</div>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
`
|
|
126
|
+
},
|
|
127
|
+
{ key: 'email', label: 'Email', sortable: true, width: '260px' },
|
|
128
|
+
{ key: 'salary', label: 'Salary', sortable: true, width: '120px' },
|
|
129
|
+
{
|
|
130
|
+
key: 'status',
|
|
131
|
+
label: 'Status',
|
|
132
|
+
sortable: true,
|
|
133
|
+
width: '120px',
|
|
134
|
+
render: (row) => `<span class="demo-badge">${String(row['status'] ?? '')}</span>`
|
|
135
|
+
}
|
|
136
|
+
];
|
|
137
|
+
|
|
138
|
+
config: DynamicDataTableConfig = {
|
|
139
|
+
title: 'Users',
|
|
140
|
+
features: {
|
|
141
|
+
export: true,
|
|
142
|
+
sorting: true,
|
|
143
|
+
searching: true,
|
|
144
|
+
pagination: true,
|
|
145
|
+
rowsPerPage: true,
|
|
146
|
+
actions: true,
|
|
147
|
+
checkboxSelection: true
|
|
148
|
+
},
|
|
149
|
+
rowsPerPageOptions: [5, 10, 25],
|
|
150
|
+
defaultRowsPerPage: 10,
|
|
151
|
+
exportOptions: {
|
|
152
|
+
fileName: 'users-export',
|
|
153
|
+
formats: ['csv', 'excel']
|
|
154
|
+
},
|
|
155
|
+
actions: [
|
|
156
|
+
{ label: 'Details', icon: 'bi bi-eye', id: 'details' },
|
|
157
|
+
{ label: 'Archive', icon: 'bi bi-archive', id: 'archive' },
|
|
158
|
+
{ label: 'Delete', icon: 'bi bi-trash', id: 'delete', danger: true }
|
|
159
|
+
]
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
onAction(event: DataTableActionEvent): void {
|
|
163
|
+
console.log('Action event:', event);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
onSelection(rows: unknown[]): void {
|
|
167
|
+
console.log('Selected rows:', rows);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
onSort(event: { key: string | null; direction: 'asc' | 'desc' }): void {
|
|
171
|
+
console.log('Sort changed:', event);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
onPage(page: number): void {
|
|
175
|
+
console.log('Page changed:', page);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
onExport(event: unknown): void {
|
|
179
|
+
console.log('Export triggered:', event);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Global Styles For Custom Rendered HTML
|
|
185
|
+
|
|
186
|
+
If you use the `render` function in a column, it returns an HTML string.
|
|
187
|
+
Those styles should usually be defined in your app's global stylesheet, for example `src/styles.css`.
|
|
188
|
+
|
|
189
|
+
Example:
|
|
190
|
+
|
|
191
|
+
```css
|
|
192
|
+
.demo-user {
|
|
193
|
+
display: flex;
|
|
194
|
+
align-items: center;
|
|
195
|
+
gap: 10px;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.demo-avatar {
|
|
199
|
+
width: 34px;
|
|
200
|
+
height: 34px;
|
|
201
|
+
border-radius: 999px;
|
|
202
|
+
display: grid;
|
|
203
|
+
place-items: center;
|
|
204
|
+
color: #fff;
|
|
205
|
+
background: linear-gradient(145deg, #4f46e5, #6d67ff);
|
|
206
|
+
font-size: 12px;
|
|
207
|
+
font-weight: 700;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.demo-name {
|
|
211
|
+
font-weight: 600;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.demo-subtitle {
|
|
215
|
+
font-size: 12px;
|
|
216
|
+
color: #6d7895;
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Inputs
|
|
221
|
+
|
|
222
|
+
### `config: DynamicDataTableConfig`
|
|
223
|
+
|
|
224
|
+
Main table configuration.
|
|
225
|
+
|
|
226
|
+
### `columns: DataTableColumn[]`
|
|
227
|
+
|
|
228
|
+
Column definitions for the table.
|
|
229
|
+
|
|
230
|
+
### `data: Record<string, unknown>[]`
|
|
231
|
+
|
|
232
|
+
Array of row objects.
|
|
233
|
+
|
|
234
|
+
## Outputs
|
|
235
|
+
|
|
236
|
+
### `actionSelected`
|
|
237
|
+
|
|
238
|
+
Triggered when a row action is clicked.
|
|
239
|
+
|
|
240
|
+
Type:
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
DataTableActionEvent<T>
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Shape:
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
{
|
|
250
|
+
action: DataTableAction<T>;
|
|
251
|
+
row: T;
|
|
252
|
+
rowIndex: number;
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### `selectionChange`
|
|
257
|
+
|
|
258
|
+
Triggered when selected rows change.
|
|
259
|
+
|
|
260
|
+
### `sortChange`
|
|
261
|
+
|
|
262
|
+
Triggered when sorting changes.
|
|
263
|
+
|
|
264
|
+
Shape:
|
|
265
|
+
|
|
266
|
+
```ts
|
|
267
|
+
{ key: string | null; direction: 'asc' | 'desc' }
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### `pageChange`
|
|
271
|
+
|
|
272
|
+
Triggered when the current page changes.
|
|
273
|
+
|
|
274
|
+
### `exportTriggered`
|
|
275
|
+
|
|
276
|
+
Triggered before CSV or Excel export is downloaded.
|
|
277
|
+
|
|
278
|
+
## Type Reference
|
|
279
|
+
|
|
280
|
+
### `DataTableColumn`
|
|
281
|
+
|
|
282
|
+
```ts
|
|
283
|
+
export interface DataTableColumn<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
284
|
+
key: keyof T | string;
|
|
285
|
+
label: string;
|
|
286
|
+
sortable?: boolean;
|
|
287
|
+
width?: string | number;
|
|
288
|
+
render?: (row: T) => string;
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### `DataTableAction`
|
|
293
|
+
|
|
294
|
+
```ts
|
|
295
|
+
export interface DataTableAction<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
296
|
+
label: string;
|
|
297
|
+
icon?: string;
|
|
298
|
+
danger?: boolean;
|
|
299
|
+
id?: string;
|
|
92
300
|
}
|
|
93
301
|
```
|
|
94
302
|
|
|
95
|
-
|
|
303
|
+
### `DynamicDataTableConfig`
|
|
96
304
|
|
|
97
|
-
|
|
305
|
+
```ts
|
|
306
|
+
export interface DynamicDataTableConfig<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
307
|
+
title?: string;
|
|
308
|
+
features?: {
|
|
309
|
+
export?: boolean;
|
|
310
|
+
sorting?: boolean;
|
|
311
|
+
searching?: boolean;
|
|
312
|
+
pagination?: boolean;
|
|
313
|
+
rowsPerPage?: boolean;
|
|
314
|
+
actions?: boolean;
|
|
315
|
+
checkboxSelection?: boolean;
|
|
316
|
+
};
|
|
317
|
+
rowsPerPageOptions?: number[];
|
|
318
|
+
defaultRowsPerPage?: number;
|
|
319
|
+
exportOptions?: {
|
|
320
|
+
fileName?: string;
|
|
321
|
+
formats?: ('csv' | 'excel')[];
|
|
322
|
+
};
|
|
323
|
+
columns?: DataTableColumn<T>[];
|
|
324
|
+
actions?: DataTableAction<T>[];
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Public Methods
|
|
98
329
|
|
|
99
|
-
|
|
100
|
-
- `columns: DataTableColumn[]`
|
|
101
|
-
- `data: Record<string, unknown>[]`
|
|
330
|
+
You can access the component instance with `@ViewChild`.
|
|
102
331
|
|
|
103
|
-
|
|
332
|
+
```ts
|
|
333
|
+
import { ViewChild } from '@angular/core';
|
|
334
|
+
import { DynamicDatatableComponent } from 'ng-dynamic-datatable';
|
|
104
335
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
- `pageChange`
|
|
109
|
-
- `exportTriggered`
|
|
336
|
+
@ViewChild(DynamicDatatableComponent)
|
|
337
|
+
private table?: DynamicDatatableComponent;
|
|
338
|
+
```
|
|
110
339
|
|
|
111
|
-
|
|
340
|
+
Available methods:
|
|
112
341
|
|
|
113
342
|
- `refresh()`
|
|
114
343
|
- `updateData(newData)`
|
|
@@ -116,19 +345,138 @@ Public methods:
|
|
|
116
345
|
- `getSelectedRows()`
|
|
117
346
|
- `clearSelection()`
|
|
118
347
|
|
|
119
|
-
|
|
348
|
+
Example:
|
|
349
|
+
|
|
350
|
+
```ts
|
|
351
|
+
reloadData(): void {
|
|
352
|
+
this.table?.updateData([
|
|
353
|
+
{ id: 1, name: 'Updated User' }
|
|
354
|
+
]);
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## Local Development
|
|
359
|
+
|
|
360
|
+
### 1. Install workspace dependencies
|
|
361
|
+
|
|
362
|
+
From the workspace root:
|
|
363
|
+
|
|
364
|
+
```bash
|
|
365
|
+
npm install
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
If your workspace contains a separate Angular demo app, install its dependencies too.
|
|
369
|
+
|
|
370
|
+
### 2. Build the library
|
|
371
|
+
|
|
372
|
+
From the workspace root:
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
npx ng build dynamic-datatable
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
Build output is generated in:
|
|
379
|
+
|
|
380
|
+
```bash
|
|
381
|
+
dist/dynamic-datatable
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### 3. Test inside a consumer Angular app
|
|
385
|
+
|
|
386
|
+
In a separate Angular app:
|
|
387
|
+
|
|
388
|
+
```bash
|
|
389
|
+
npm install ng-dynamic-datatable@latest
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
Then build the app:
|
|
393
|
+
|
|
394
|
+
```bash
|
|
395
|
+
npm run build
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
## Publishing A New Version
|
|
399
|
+
|
|
400
|
+
### 1. Update version
|
|
401
|
+
|
|
402
|
+
Update the version in:
|
|
120
403
|
|
|
121
404
|
```bash
|
|
122
|
-
|
|
405
|
+
projects/dynamic-datatable/package.json
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
Example:
|
|
409
|
+
|
|
410
|
+
```json
|
|
411
|
+
{
|
|
412
|
+
"version": "0.0.7"
|
|
413
|
+
}
|
|
123
414
|
```
|
|
124
415
|
|
|
125
|
-
|
|
416
|
+
### 2. Build the library
|
|
126
417
|
|
|
127
|
-
|
|
418
|
+
```bash
|
|
419
|
+
npx ng build dynamic-datatable
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
### 3. Publish from the dist package
|
|
128
423
|
|
|
129
424
|
```bash
|
|
130
425
|
cd dist/dynamic-datatable
|
|
131
426
|
npm publish --access public
|
|
132
427
|
```
|
|
133
428
|
|
|
134
|
-
|
|
429
|
+
Important:
|
|
430
|
+
|
|
431
|
+
- Always publish from `dist/dynamic-datatable`
|
|
432
|
+
- Do not publish from the workspace root
|
|
433
|
+
- Make sure you are logged into npm
|
|
434
|
+
- Wait a few moments after publishing before installing the new version in another app
|
|
435
|
+
|
|
436
|
+
### 4. Upgrade a consuming Angular app
|
|
437
|
+
|
|
438
|
+
```bash
|
|
439
|
+
npm install ng-dynamic-datatable@latest
|
|
440
|
+
npm run build
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
If npm does not find the new version immediately, wait briefly and retry.
|
|
444
|
+
|
|
445
|
+
## Troubleshooting
|
|
446
|
+
|
|
447
|
+
### Icons are not showing
|
|
448
|
+
|
|
449
|
+
Install and include `bootstrap-icons` in your app styles.
|
|
450
|
+
|
|
451
|
+
### Custom rendered HTML styles are not applied
|
|
452
|
+
|
|
453
|
+
Move those styles to the consuming app's global stylesheet.
|
|
454
|
+
|
|
455
|
+
### Sorting does not work as expected
|
|
456
|
+
|
|
457
|
+
Ensure the column has `sortable: true` and that values are consistently formatted.
|
|
458
|
+
|
|
459
|
+
### Action dropdown appears clipped
|
|
460
|
+
|
|
461
|
+
This usually depends on available space around the row and container overflow. Use the latest package version because menu positioning has been improved in recent patches.
|
|
462
|
+
|
|
463
|
+
## Build Command
|
|
464
|
+
|
|
465
|
+
```bash
|
|
466
|
+
npx ng build dynamic-datatable
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
## Exported API
|
|
470
|
+
|
|
471
|
+
This package exports:
|
|
472
|
+
|
|
473
|
+
- `DynamicDatatableComponent`
|
|
474
|
+
- `DataTableColumn`
|
|
475
|
+
- `DataTableAction`
|
|
476
|
+
- `DynamicDataTableConfig`
|
|
477
|
+
- `DataTableActionEvent`
|
|
478
|
+
- `DataTableExportEvent`
|
|
479
|
+
|
|
480
|
+
## License
|
|
481
|
+
|
|
482
|
+
MIT
|