@oneteme/jquery-table 0.0.1 → 0.0.2
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 +439 -122
- package/esm2022/lib/component/export.manager.mjs +45 -0
- package/esm2022/lib/component/group-by.manager.mjs +99 -0
- package/esm2022/lib/component/lazy-column-manager.mjs +99 -0
- package/esm2022/lib/component/slice-panel/slice-panel.component.mjs +43 -37
- package/esm2022/lib/component/slice-panel/slice-panel.model.mjs +1 -1
- package/esm2022/lib/component/table-preferences.manager.mjs +38 -0
- package/esm2022/lib/component/table.component.mjs +681 -370
- package/esm2022/lib/component/table.constants.mjs +31 -0
- package/esm2022/lib/component/table.utils.mjs +2 -2
- package/esm2022/lib/component/view/view.facade.mjs +298 -0
- package/esm2022/lib/jqt-i18n.token.mjs +41 -0
- package/esm2022/lib/jquery-table.model.mjs +14 -2
- package/esm2022/public-api.mjs +2 -1
- package/fesm2022/oneteme-jquery-table.mjs +1377 -408
- package/fesm2022/oneteme-jquery-table.mjs.map +1 -1
- package/lib/component/export.manager.d.ts +16 -0
- package/lib/component/group-by.manager.d.ts +44 -0
- package/lib/component/lazy-column-manager.d.ts +26 -0
- package/lib/component/slice-panel/slice-panel.component.d.ts +11 -3
- package/lib/component/slice-panel/slice-panel.model.d.ts +11 -1
- package/lib/component/table-preferences.manager.d.ts +17 -0
- package/lib/component/table.component.d.ts +162 -27
- package/lib/component/table.constants.d.ts +30 -0
- package/lib/component/view/view.facade.d.ts +93 -0
- package/lib/jqt-i18n.token.d.ts +87 -0
- package/lib/jquery-table.model.d.ts +79 -0
- package/package.json +2 -2
- package/public-api.d.ts +1 -0
package/README.md
CHANGED
|
@@ -1,16 +1,24 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @oneteme/jquery-table
|
|
2
2
|
|
|
3
3
|
Bibliothèque Angular qui encapsule Angular Material Table avec une API orientée configuration runtime.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
7
|
+
- Configuration déclarative du tableau via `TableProvider`
|
|
8
|
+
- Colonnes optionnelles ajoutables/supprimables à l'exécution via menu View
|
|
9
|
+
- Réordonnancement des colonnes par glisser-déposer
|
|
10
|
+
- Tri natif Material par colonne
|
|
11
|
+
- Recherche textuelle temps réel
|
|
12
|
+
- Pagination standard et pagination par groupe
|
|
13
|
+
- **Group by** : regroupement des lignes par colonne, groupes pliables/dépliables, pagination indépendante par groupe
|
|
14
|
+
- **Slice panel** : filtres catégoriels latéraux, statiques (prédéfinis) ou dynamiques (colonne valeurs uniques), multi-sélection configurable
|
|
15
|
+
- **Chargement paresseux** (lazy) de cellules via Observable par colonne
|
|
16
|
+
- Rendus de cellule personnalisés via directive `jqtCellDef`
|
|
17
|
+
- État de chargement (`isLoading`) et état vide configurable
|
|
18
|
+
- Événement de clic sur ligne (`rowSelected`)
|
|
19
|
+
- CSS variables pour la personnalisation visuelle complète
|
|
20
|
+
- Compatible mode allégé : `[dataSource]` + `[displayedColumns]` sans `config`
|
|
21
|
+
- Intégration `@oneteme/jquery-core` (`DataProvider`)
|
|
14
22
|
|
|
15
23
|
## Installation
|
|
16
24
|
|
|
@@ -18,174 +26,483 @@ Bibliothèque Angular qui encapsule Angular Material Table avec une API orienté
|
|
|
18
26
|
npm install @oneteme/jquery-core @oneteme/jquery-table @angular/material @angular/cdk
|
|
19
27
|
```
|
|
20
28
|
|
|
29
|
+
---
|
|
30
|
+
|
|
21
31
|
## Utilisation rapide
|
|
22
32
|
|
|
23
33
|
```ts
|
|
24
|
-
import { Component } from '@angular/core';
|
|
25
34
|
import { TableComponent, TableProvider, col } from '@oneteme/jquery-table';
|
|
26
35
|
|
|
27
36
|
interface Row {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
37
|
+
id: number;
|
|
38
|
+
name: string;
|
|
39
|
+
status: 'active' | 'inactive';
|
|
40
|
+
team: string;
|
|
32
41
|
}
|
|
33
42
|
|
|
34
43
|
@Component({
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
template: `
|
|
38
|
-
<jquery-table
|
|
39
|
-
[config]="tableConfig"
|
|
40
|
-
(columnAdded)="onColumnAdded($event)"
|
|
41
|
-
(columnRemoved)="onColumnRemoved($event)"
|
|
42
|
-
(categorySelected)="onCategorySelected($event)"
|
|
43
|
-
></jquery-table>
|
|
44
|
-
`,
|
|
44
|
+
imports: [TableComponent],
|
|
45
|
+
template: `<jquery-table [config]="table" [data]="rows" (rowSelected)="onRow($event)"></jquery-table>`,
|
|
45
46
|
})
|
|
46
47
|
export class DemoComponent {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
48
|
+
rows: Row[] = [];
|
|
49
|
+
|
|
50
|
+
table: TableProvider<Row> = {
|
|
51
|
+
title: 'Utilisateurs',
|
|
52
|
+
columns: [
|
|
53
|
+
col('id', 'ID'),
|
|
54
|
+
col('name', 'Nom', { sortable: true }),
|
|
55
|
+
col('status', 'Statut', { sliceable: true }),
|
|
56
|
+
col('team', 'Équipe', { groupable: true, optional: true }),
|
|
57
|
+
],
|
|
58
|
+
slices: [
|
|
59
|
+
{
|
|
60
|
+
title: 'Statut',
|
|
61
|
+
columnKey: 'status',
|
|
62
|
+
categories: [
|
|
63
|
+
{ key: 'active', label: 'Actif', filter: r => r.status === 'active' },
|
|
64
|
+
{ key: 'inactive', label: 'Inactif', filter: r => r.status === 'inactive' },
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
search: { enabled: true },
|
|
69
|
+
pagination: { enabled: true, pageSize: 20 },
|
|
70
|
+
view: { enabled: true, enableColumnDragDrop: true },
|
|
71
|
+
export: { enabled: true, filename: 'utilisateurs' },
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
onRow(row: Row) { console.log(row); }
|
|
71
75
|
}
|
|
72
76
|
```
|
|
73
77
|
|
|
74
|
-
|
|
78
|
+
---
|
|
75
79
|
|
|
76
|
-
|
|
80
|
+
## Mode allégé compatibilité `dataSource` / `displayedColumns`
|
|
77
81
|
|
|
78
|
-
|
|
79
|
-
<!-- Avant -->
|
|
80
|
-
<!-- <table mat-table [dataSource]="dataSource"> ... -->
|
|
82
|
+
Pour une migration minimale depuis une `mat-table` existante :
|
|
81
83
|
|
|
82
|
-
|
|
84
|
+
```html
|
|
83
85
|
<jquery-table
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
[dataSource]="rows"
|
|
87
|
+
[displayedColumns]="['id', 'name', 'status']"
|
|
88
|
+
[columnLabels]="{ id: 'ID', name: 'Nom', status: 'Statut' }"
|
|
89
|
+
[isLoading]="loading"
|
|
87
90
|
></jquery-table>
|
|
88
91
|
```
|
|
89
92
|
|
|
93
|
+
Le `config` complet reste disponible pour activer les fonctionnalités avancées.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## API `TableComponent`
|
|
98
|
+
|
|
99
|
+
### Inputs
|
|
100
|
+
|
|
101
|
+
| Propriété | Type | Description |
|
|
102
|
+
|-----------|------|-------------|
|
|
103
|
+
| `config` | `TableProvider<T>` | Configuration principale (colonnes, données, comportements) |
|
|
104
|
+
| `data` | `T[]` | Données en entrée directe (remplace `config.data`) |
|
|
105
|
+
| `dataSource` | `T[] \| { data: T[] }` | Alias compatibilité Material |
|
|
106
|
+
| `displayedColumns` | `string[]` | Alias compatibilité Material clés de colonnes à afficher |
|
|
107
|
+
| `columnsConfig` | `TableColumnProvider<T>[]` | Configuration des colonnes (remplace `config.columns`) |
|
|
108
|
+
| `columnLabels` | `Record<string, string>` | Labels des colonnes pour le mode allégé |
|
|
109
|
+
| `isLoading` | `boolean` | Affiche l'état de chargement (défaut : `false`) |
|
|
110
|
+
| `view` | `TableViewConfig` | Surcharge `config.view` si défini (mode HTML) |
|
|
111
|
+
|
|
112
|
+
### Outputs
|
|
113
|
+
|
|
114
|
+
| Événement | Payload | Description |
|
|
115
|
+
|-----------|---------|-------------|
|
|
116
|
+
| `rowSelected` | `T` | Ligne cliquée |
|
|
117
|
+
| `columnAdded` | `TableColumnProvider<T>` | Colonne ajoutée aux colonnes actives |
|
|
118
|
+
| `columnRemoved` | `TableColumnProvider<T>` | Colonne retirée des colonnes actives |
|
|
119
|
+
| `categorySelected` | `string` | Catégorie de slice sélectionnée |
|
|
120
|
+
| `addRequested` | `void` | Clic sur le bouton d'ajout de colonne |
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## API — `TableProvider<T>`
|
|
125
|
+
|
|
90
126
|
```ts
|
|
91
|
-
|
|
127
|
+
interface TableProvider<T = any> {
|
|
128
|
+
columns?: TableColumnProvider<T>[];
|
|
129
|
+
title?: string;
|
|
92
130
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
131
|
+
slices?: SliceConfig<T>[]; // Filtres catégoriels (slice panel)
|
|
132
|
+
enableSliceToggle?: boolean; // Défaut : true
|
|
133
|
+
|
|
134
|
+
search?: TableSearchConfig;
|
|
135
|
+
pagination?: TablePaginationConfig;
|
|
136
|
+
view?: TableViewConfig;
|
|
137
|
+
labels?: TableLabelsConfig;
|
|
138
|
+
export?: TableExportConfig<T>;
|
|
139
|
+
|
|
140
|
+
defaultSort?: { active: string; direction: 'asc' | 'desc' };
|
|
141
|
+
rowClass?: (row: T, index: number) => string | string[] | Record<string, boolean>;
|
|
142
|
+
}
|
|
98
143
|
```
|
|
99
144
|
|
|
100
|
-
|
|
145
|
+
> **Note** : les données (`data`) et l’état de chargement (`isLoading`) sont des `@Input` séparés
|
|
146
|
+
> sur le composant, pas des champs de `TableProvider`.
|
|
101
147
|
|
|
102
|
-
|
|
148
|
+
---
|
|
103
149
|
|
|
104
|
-
|
|
150
|
+
## API — `TableColumnProvider<T>`
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
interface TableColumnProvider<T = any> {
|
|
154
|
+
key: string;
|
|
155
|
+
header?: string; // Label de l'entête
|
|
156
|
+
icon?: string; // Icône Material (affiché dans l'entête)
|
|
157
|
+
value?: DataProvider<any>; // (row, index) => valeur affichée
|
|
158
|
+
sortValue?: DataProvider<any>; // Valeur pour le tri si différente de value
|
|
159
|
+
sortable?: boolean;
|
|
160
|
+
width?: string; // Largeur CSS en px uniquement pour le calcul min-width (ex: '120px')
|
|
161
|
+
// Les unités %, em, rem sont ignorées dans le calcul de tableMinWidth
|
|
162
|
+
|
|
163
|
+
optional?: boolean; // Colonne masquée par défaut, ajoutables via View menu
|
|
164
|
+
removable?: boolean; // Peut être retirée manuellement
|
|
165
|
+
|
|
166
|
+
groupable?: boolean; // Disponible comme critère de regroupement dans View menu
|
|
167
|
+
sliceable?: boolean; // Disponible comme slice dynamique dans View menu
|
|
168
|
+
searchValue?: DataProvider<string>; // Valeur utilisée par la recherche texte (si différente de value)
|
|
169
|
+
|
|
170
|
+
lazy?: {
|
|
171
|
+
fetchFn: () => Observable<any[]>; // Retourne un tableau dans le même ordre que les lignes
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
```
|
|
105
175
|
|
|
106
|
-
|
|
107
|
-
- `displayedColumns`: alias compatible Material (`string[]`)
|
|
108
|
-
- `columnLabels`: labels optionnels pour `displayedColumns`
|
|
109
|
-
- `config.showColumnSettings`: active les menus `⋯` en header de colonne
|
|
110
|
-
- `config.maxFilterValuesPerColumn`: limite le nombre de valeurs proposées dans `Filter by values`
|
|
111
|
-
- `config.columnUtilityActions`: actions custom globales par colonne
|
|
112
|
-
- `config.columns`: colonnes initiales visibles
|
|
113
|
-
- `config.optionalColumns` (ou `config.availableColumns`): colonnes optionnelles ajoutables via `+`
|
|
114
|
-
- `config.showAddColumnButton`: active/désactive le bouton `+`
|
|
115
|
-
- `config.showOptionsButton`: active/désactive le bouton `Options`
|
|
116
|
-
- `config.bottomActionsLabel`: libellé des actions dockées en bas-gauche
|
|
117
|
-
- `config.enableColumnRemoval`: autorise la suppression des colonnes
|
|
118
|
-
- `config.categorySlice`: configuration du panel de catégories à gauche
|
|
119
|
-
- `config.data`: dataset source
|
|
120
|
-
|
|
121
|
-
### Smart adaptation (intelligence data-driven)
|
|
122
|
-
Le wrapper est volontairement simple: pas de système d'inférence automatique complexe.
|
|
123
|
-
Le développeur fournit explicitement les colonnes de base, les colonnes optionnelles et les filtres.
|
|
176
|
+
---
|
|
124
177
|
|
|
125
|
-
|
|
178
|
+
## Helper `col()`
|
|
179
|
+
|
|
180
|
+
Raccourci pour déclarer une colonne sans verbosité :
|
|
181
|
+
|
|
182
|
+
```ts
|
|
183
|
+
import { col } from '@oneteme/jquery-table';
|
|
184
|
+
|
|
185
|
+
columns: [
|
|
186
|
+
col('name', 'Nom'),
|
|
187
|
+
col('status', 'Statut', { sortable: false, groupable: true }),
|
|
188
|
+
col('team', 'Équipe', { optional: true }),
|
|
189
|
+
]
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## API — Sous-configurations
|
|
195
|
+
|
|
196
|
+
### `TableSearchConfig`
|
|
126
197
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
198
|
+
```ts
|
|
199
|
+
interface TableSearchConfig {
|
|
200
|
+
enabled?: boolean;
|
|
201
|
+
initialQuery?: string; // Terme de recherche pré-rempli au chargement
|
|
202
|
+
searchColumns?: string[]; // Restreint la recherche à ces clés de colonnes
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### `TablePaginationConfig`
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
interface TablePaginationConfig {
|
|
210
|
+
enabled?: boolean;
|
|
211
|
+
pageSize?: number;
|
|
212
|
+
pageSizeOptions?: number[];
|
|
213
|
+
pageSizeOptionsGroupBy?: number[]; // Options spécifiques au mode Group by
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### `TableViewConfig`
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
interface TableViewConfig {
|
|
221
|
+
enabled?: boolean; // Défaut : false active le bouton View
|
|
222
|
+
enableColumnRemoval?: boolean; // Défaut : true autorise la suppression de colonnes
|
|
223
|
+
enableColumnDragDrop?: boolean; // Défaut : false active le réordonnancement drag & drop
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### `TableLabelsConfig`
|
|
228
|
+
|
|
229
|
+
```ts
|
|
230
|
+
interface TableLabelsConfig {
|
|
231
|
+
empty?: string; // Défaut : 'Aucune donnée' (ou la valeur i18n injectée)
|
|
232
|
+
loading?: string; // Défaut : 'Chargement des données...' (ou la valeur i18n injectée)
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### `TableExportConfig<T>`
|
|
237
|
+
|
|
238
|
+
```ts
|
|
239
|
+
interface TableExportConfig<T = any> {
|
|
240
|
+
enabled?: boolean; // Affiche le bouton Export
|
|
241
|
+
filename?: string; // Nom du fichier sans extension (défaut : 'export')
|
|
242
|
+
transform?: (row: T) => Record<string, string>; // Transforme chaque ligne avant export
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
L’export ne porte que sur les **données filtrées** (slice + recherche) et les **colonnes visibles**.
|
|
247
|
+
Le fichier est généré avec un BOM UTF-8 pour une compatibilité Excel correcte.
|
|
132
248
|
|
|
133
|
-
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## i18n
|
|
252
|
+
|
|
253
|
+
Tous les labels de l’interface sont personnalisables via un `InjectionToken` :
|
|
134
254
|
|
|
135
255
|
```ts
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
256
|
+
import { JQT_I18N } from '@oneteme/jquery-table';
|
|
257
|
+
|
|
258
|
+
// Dans AppModule ou un provider racine
|
|
259
|
+
providers: [
|
|
260
|
+
{
|
|
261
|
+
provide: JQT_I18N,
|
|
262
|
+
useValue: {
|
|
263
|
+
searchPlaceholder: 'Search…',
|
|
264
|
+
emptyState: 'No data',
|
|
265
|
+
loadingState: 'Loading…',
|
|
266
|
+
viewNoneSelected: 'None',
|
|
267
|
+
groupRemove: 'Remove grouping',
|
|
268
|
+
exportButtonLabel: 'Export',
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
]
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Seuls les champs fournis écrasent les défauts français. Voir `JqtI18n` pour la liste complète (24 labels).
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Fonctionnalité — Group by
|
|
279
|
+
|
|
280
|
+
Le regroupement s'active en ajoutant `groupable: true` sur une ou plusieurs colonnes. L'utilisateur choisit ensuite la colonne de regroupement depuis le menu View.
|
|
281
|
+
|
|
282
|
+
```ts
|
|
283
|
+
columns: [
|
|
284
|
+
{ key: 'team', header: 'Équipe', groupable: true },
|
|
285
|
+
{ key: 'status', header: 'Statut', groupable: true },
|
|
286
|
+
{ key: 'name', header: 'Nom' },
|
|
287
|
+
],
|
|
288
|
+
view: { enabled: true },
|
|
289
|
+
pagination: {
|
|
290
|
+
enabled: true,
|
|
291
|
+
pageSizeOptionsGroupBy: [5, 10, 25],
|
|
292
|
+
},
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Comportements inclus :
|
|
296
|
+
- Groupes pliables/dépliables individuellement
|
|
297
|
+
- Pagination indépendante par groupe
|
|
298
|
+
- Tri des entêtes de groupe (asc / desc)
|
|
299
|
+
- Scroll automatique vers l'entête du groupe actif
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Fonctionnalité — Slice panel
|
|
304
|
+
|
|
305
|
+
Le slice panel est un panneau latéral de filtres catégoriels.
|
|
306
|
+
|
|
307
|
+
### Slices statiques (catégories prédéfinies)
|
|
308
|
+
|
|
309
|
+
```ts
|
|
310
|
+
slices: [
|
|
311
|
+
{
|
|
312
|
+
title: 'Statut',
|
|
313
|
+
icon: 'circle',
|
|
314
|
+
columnKey: 'status',
|
|
315
|
+
categories: [
|
|
316
|
+
{ key: 'active', label: 'Actif', filter: r => r.status === 'active' },
|
|
317
|
+
{ key: 'inactive', label: 'Inactif', filter: r => r.status === 'inactive' },
|
|
318
|
+
],
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
title: 'Priorité',
|
|
322
|
+
columnKey: 'priority',
|
|
323
|
+
multiSelect: true,
|
|
324
|
+
bucket: r => r.priority, // Auto-génère les catégories depuis les valeurs uniques
|
|
325
|
+
},
|
|
326
|
+
],
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Slices dynamiques (depuis le menu View)
|
|
330
|
+
|
|
331
|
+
Une colonne avec `sliceable: true` peut être ajoutée dynamiquement comme slice depuis le menu View.
|
|
332
|
+
|
|
333
|
+
```ts
|
|
334
|
+
columns: [
|
|
335
|
+
{ key: 'team', header: 'Équipe', sliceable: true },
|
|
336
|
+
],
|
|
337
|
+
view: { enabled: true },
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### `SliceConfig<T>`
|
|
341
|
+
|
|
342
|
+
```ts
|
|
343
|
+
interface SliceConfig<T = any> {
|
|
344
|
+
title?: string;
|
|
345
|
+
icon?: string;
|
|
346
|
+
columnKey?: string;
|
|
347
|
+
multiSelect?: boolean; // Défaut : false
|
|
348
|
+
hidden?: boolean; // Masqué par défaut dans le panel
|
|
349
|
+
categories?: SliceCategory<T>[];
|
|
350
|
+
bucket?: (row: T) => string; // Auto-génère les catégories (ignoré si categories défini)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
interface SliceCategory<T = any> {
|
|
354
|
+
key: string;
|
|
355
|
+
label: string;
|
|
356
|
+
filter: (row: T) => boolean;
|
|
357
|
+
}
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
## Fonctionnalité — lazy columns
|
|
363
|
+
|
|
364
|
+
```ts
|
|
365
|
+
columns: [
|
|
366
|
+
{
|
|
367
|
+
key: 'details',
|
|
368
|
+
header: 'Détails',
|
|
369
|
+
lazy: {
|
|
370
|
+
fetchFn: () => this.api.getDetails(),
|
|
371
|
+
},
|
|
372
|
+
},
|
|
373
|
+
],
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
Le composant gère l'état `idle | loading | loaded | error` par colonne, avec possibilité de relancer la requête en cas d'erreur.
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
## Fonctionnalité — Cellules personnalisées (`jqtCellDef`)
|
|
381
|
+
|
|
382
|
+
```html
|
|
383
|
+
<jquery-table [config]="table">
|
|
384
|
+
|
|
385
|
+
<ng-template jqtCellDef="status" let-row>
|
|
386
|
+
<span [class]="'badge badge-' + row.status">{{ row.status }}</span>
|
|
387
|
+
</ng-template>
|
|
388
|
+
|
|
389
|
+
<ng-template jqtCellDef="actions" let-row let-index="index">
|
|
390
|
+
<button (click)="edit(row)">Éditer</button>
|
|
391
|
+
</ng-template>
|
|
392
|
+
|
|
393
|
+
</jquery-table>
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
Contexte du template :
|
|
397
|
+
- `$implicit` la ligne brute (`T`)
|
|
398
|
+
- `index` index global de la ligne
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
## Fonctionnalité — Clic sur ligne
|
|
403
|
+
|
|
404
|
+
```html
|
|
405
|
+
<jquery-table [config]="table" (rowSelected)="onRow($event)"></jquery-table>
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
La ligne brute `T` est émise via l'Output `(rowSelected)`. Pour appliquer une classe conditionnelle aux lignes, utiliser `rowClass` dans `config` :
|
|
409
|
+
|
|
410
|
+
```ts
|
|
411
|
+
config: TableProvider<Row> = {
|
|
412
|
+
rowClass: (row) => row.status === 'error' ? 'row-error' : '',
|
|
142
413
|
};
|
|
143
414
|
```
|
|
144
415
|
|
|
145
|
-
|
|
416
|
+
---
|
|
417
|
+
|
|
418
|
+
## Usage standalone — `SlicePanelComponent`
|
|
146
419
|
|
|
147
|
-
|
|
148
|
-
|
|
420
|
+
`SlicePanelComponent` est exporté et utilisable indépendamment du tableau, par exemple pour filtrer les données d'un graphique :
|
|
421
|
+
|
|
422
|
+
```html
|
|
423
|
+
<jqt-slice-panel
|
|
424
|
+
[sliceConfigs]="slices"
|
|
425
|
+
[columns]="columns"
|
|
426
|
+
[data]="rows"
|
|
427
|
+
[showCounts]="true"
|
|
428
|
+
(filterChange)="applyFilter($event)"
|
|
429
|
+
></jqt-slice-panel>
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### Inputs `SlicePanelComponent`
|
|
433
|
+
|
|
434
|
+
| Propriété | Type | Description |
|
|
435
|
+
|-----------|------|-------------|
|
|
436
|
+
| `sliceConfigs` | `SliceConfig<T>[]` | Configurations des slices |
|
|
437
|
+
| `columns` | `SliceColumnDef<T>[]` | Définitions des colonnes pour la résolution des valeurs |
|
|
438
|
+
| `data` | `T[]` | Données source |
|
|
439
|
+
| `lazyData` | `Map<string, Map<any,any>>` | Valeurs lazy chargées |
|
|
440
|
+
| `lazyStatus` | `Map<string, 'idle'\|'loading'\|'loaded'\|'error'>` | État par colonne lazy |
|
|
441
|
+
| `showToggle` | `boolean` | Affiche le bouton collapse du panel (défaut : `true`) |
|
|
442
|
+
| `showCounts` | `boolean` | Affiche le nombre de lignes par catégorie (défaut : `true`) |
|
|
443
|
+
| `collapsedByDefault` | `boolean` | Les slices démarrent repliés (défaut : `false`) |
|
|
444
|
+
| `alwaysShow` | `boolean` | Affiche le panel même si vide (défaut : `false`) |
|
|
445
|
+
|
|
446
|
+
### Outputs `SlicePanelComponent`
|
|
447
|
+
|
|
448
|
+
| Événement | Payload | Description |
|
|
449
|
+
|-----------|---------|-------------|
|
|
450
|
+
| `filterChange` | `(row: T) => boolean` | Prédicat de filtre à appliquer |
|
|
451
|
+
| `activeKeysChange` | `string[][]` | Clés actives par slice |
|
|
452
|
+
| `dynamicSliceKeysChange` | `string[]` | Clés des slices dynamiques actives |
|
|
453
|
+
| `collapsedChange` | `boolean` | État replié/déplié du panel |
|
|
454
|
+
|
|
455
|
+
---
|
|
456
|
+
|
|
457
|
+
## Personnalisation visuelle — CSS variables
|
|
149
458
|
|
|
150
459
|
```scss
|
|
151
460
|
jquery-table {
|
|
152
461
|
/* Texte */
|
|
153
|
-
--jqt-title-color: #1f2937;
|
|
154
|
-
--jqt-text-color: #111827;
|
|
155
|
-
--jqt-text-secondary: #6b7280;
|
|
156
|
-
--jqt-text-muted: #9ca3af;
|
|
462
|
+
--jqt-title-color: #1f2937;
|
|
463
|
+
--jqt-text-color: #111827;
|
|
464
|
+
--jqt-text-secondary: #6b7280;
|
|
465
|
+
--jqt-text-muted: #9ca3af;
|
|
157
466
|
|
|
158
467
|
/* Surfaces */
|
|
159
|
-
--jqt-surface-color: #ffffff;
|
|
160
|
-
--jqt-surface-alt-color: #f9fafb;
|
|
161
|
-
--jqt-row-hover-bg: #f3f4f6;
|
|
468
|
+
--jqt-surface-color: #ffffff;
|
|
469
|
+
--jqt-surface-alt-color: #f9fafb;
|
|
470
|
+
--jqt-row-hover-bg: #f3f4f6;
|
|
162
471
|
|
|
163
472
|
/* Bordures */
|
|
164
|
-
--jqt-border-color: #e5e7eb;
|
|
473
|
+
--jqt-border-color: #e5e7eb;
|
|
165
474
|
|
|
166
|
-
/*
|
|
167
|
-
--jqt-group-bg: #eef2f7;
|
|
168
|
-
--jqt-group-bg-hover: #e4ecf4;
|
|
169
|
-
--jqt-group-accent: #94a3b8;
|
|
170
|
-
--jqt-group-border: #d1d9e4;
|
|
475
|
+
/* Group by */
|
|
476
|
+
--jqt-group-bg: #eef2f7;
|
|
477
|
+
--jqt-group-bg-hover: #e4ecf4;
|
|
478
|
+
--jqt-group-accent: #94a3b8;
|
|
479
|
+
--jqt-group-border: #d1d9e4;
|
|
171
480
|
|
|
172
481
|
/* Accent & danger */
|
|
173
|
-
--jqt-primary-color: #1d4ed8;
|
|
174
|
-
--jqt-danger-color: #dc2626;
|
|
482
|
+
--jqt-primary-color: #1d4ed8;
|
|
483
|
+
--jqt-danger-color: #dc2626;
|
|
175
484
|
}
|
|
176
485
|
```
|
|
177
486
|
|
|
178
|
-
|
|
487
|
+
---
|
|
179
488
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
--jqt-group-bg: #f5f3ff;
|
|
185
|
-
--jqt-group-border: #ddd6fe;
|
|
186
|
-
}
|
|
489
|
+
## Utilitaires exportés
|
|
490
|
+
|
|
491
|
+
```ts
|
|
492
|
+
import { normalizeCellValue, humanizeKey, getFrenchPaginatorIntl } from '@oneteme/jquery-table';
|
|
187
493
|
```
|
|
188
494
|
|
|
495
|
+
| Fonction | Description |
|
|
496
|
+
|----------|-------------|
|
|
497
|
+
| `normalizeCellValue(value)` | Convertit n'importe quelle valeur de cellule en string affichable (gère `null`, `Date`, `Array`, objet `{label}` / `{name}`) |
|
|
498
|
+
| `humanizeKey(key)` | Transforme `camelCase` / `snake_case` en label lisible (`createdAt` → `"Created at"`) |
|
|
499
|
+
| `col(key, header, overrides?)` | Raccourci pour créer un `TableColumnProvider` en une ligne |
|
|
500
|
+
| `getFrenchPaginatorIntl()` | Retourne un `MatPaginatorIntl` avec les labels en français |
|
|
501
|
+
|
|
502
|
+
> **`normalizeCellValue`** utilise la locale navigateur (et non fr-FR) pour les dates.
|
|
503
|
+
|
|
504
|
+
---
|
|
505
|
+
|
|
189
506
|
## Build
|
|
190
507
|
|
|
191
508
|
```bash
|