data-table-list 1.0.0 → 1.0.1

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/DOCUMENTATION.md CHANGED
@@ -116,8 +116,9 @@ In questo scenario, i dati sono interamente caricati in memoria. Il componente g
116
116
  ```html
117
117
  <script setup lang="ts">
118
118
  import { ref } from 'vue';
119
- import DataTableList from '@/component/commons/DataTableList.vue';
120
- import type { DataTableConf } from '@/model/Models';
119
+ import { DataTableList, Avatar } from 'data-table-list';
120
+ import type { DataTableConf } from 'data-table-list';
121
+ import 'data-table-list/dist/data-table-list.css';
121
122
 
122
123
  const searchFilter = ref('');
123
124
 
@@ -214,9 +215,9 @@ Se si necessita di inserire markup HTML complesso (es. Badge di stato, icone, o
214
215
  ```html
215
216
  <script setup lang="ts">
216
217
  import { ref } from 'vue';
217
- import DataTableList from '@/component/commons/DataTableList.vue';
218
- import Avatar from '@/component/commons/Avatar.vue';
219
- import type { DataTableConf } from '@/model/Models';
218
+ import { DataTableList, Avatar } from 'data-table-list';
219
+ import type { DataTableConf } from 'data-table-list';
220
+ import 'data-table-list/dist/data-table-list.css';
220
221
 
221
222
  const tableConfig = ref<DataTableConf>({
222
223
  columns: [
@@ -274,8 +275,9 @@ Il componente supporta la selezione di elementi tramite una colonna di checkbox
274
275
  ```html
275
276
  <script setup lang="ts">
276
277
  import { ref } from 'vue';
277
- import DataTableList from '@/component/commons/DataTableList.vue';
278
- import type { DataTableConf } from '@/model/Models';
278
+ import { DataTableList, Avatar } from 'data-table-list';
279
+ import type { DataTableConf } from 'data-table-list';
280
+ import 'data-table-list/dist/data-table-list.css';
279
281
 
280
282
  const tableConfig = ref<DataTableConf>({
281
283
  columns: [
@@ -329,8 +331,9 @@ Invece di mostrare i tre pulsanti standard in linea (view, update, delete), è p
329
331
  ```html
330
332
  <script setup lang="ts">
331
333
  import { ref } from 'vue';
332
- import DataTableList from '@/component/commons/DataTableList.vue';
333
- import type { DataTableConf } from '@/model/Models';
334
+ import { DataTableList, Avatar } from 'data-table-list';
335
+ import type { DataTableConf } from 'data-table-list';
336
+ import 'data-table-list/dist/data-table-list.css';
334
337
 
335
338
  const tableConfig = ref<DataTableConf>({
336
339
  columns: [
@@ -403,8 +406,9 @@ Se la sorgente dati ha molti elementi, la paginazione deve avvenire sul server.
403
406
  ```html
404
407
  <script setup lang="ts">
405
408
  import { ref, onMounted } from 'vue';
406
- import DataTableList from '@/component/commons/DataTableList.vue';
407
- import type { DataTableConf } from '@/model/Models';
409
+ import { DataTableList, Avatar } from 'data-table-list';
410
+ import type { DataTableConf } from 'data-table-list';
411
+ import 'data-table-list/dist/data-table-list.css';
408
412
 
409
413
  // Stato locale per i dati e il caricamento
410
414
  const items = ref<any[]>([]);
@@ -499,8 +503,9 @@ Il componente offre la possibilità di abilitare un pulsante per il download dei
499
503
  ```html
500
504
  <script setup lang="ts">
501
505
  import { ref } from 'vue';
502
- import DataTableList from '@/component/commons/DataTableList.vue';
503
- import type { DataTableConf } from '@/model/Models';
506
+ import { DataTableList, Avatar } from 'data-table-list';
507
+ import type { DataTableConf } from 'data-table-list';
508
+ import 'data-table-list/dist/data-table-list.css';
504
509
 
505
510
  const searchFilter = ref('');
506
511
 
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License Copyright (c) 2026 msalvo
2
+
3
+ Permission is hereby granted, free of
4
+ charge, to any person obtaining a copy of this software and associated
5
+ documentation files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use, copy, modify, merge,
7
+ publish, distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to the
9
+ following conditions:
10
+
11
+ The above copyright notice and this permission notice
12
+ (including the next paragraph) shall be included in all copies or substantial
13
+ portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
16
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
18
+ EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # data-table-list
1
+ # Guida all'Utilizzo e all'Implementazione di `DataTableList`
2
2
 
3
3
  `DataTableList` è un componente riutilizzabile sviluppato in **Vue 3** (con TypeScript e Composition API). Offre una tabella dati flessibile con supporto nativo per paginazione, ordinamento, filtraggio, azioni di riga, esportazione dati, e selezione multipla tramite checkbox.
4
4
 
@@ -7,7 +7,7 @@
7
7
  ## Project Setup
8
8
 
9
9
  ```sh
10
- npm install data-table-list
10
+ npm install data-table-list@latest
11
11
  ```
12
12
 
13
13
  ---
@@ -23,3 +23,542 @@ import 'data-table-list/dist/data-table-list.css'; // This imports the new stabl
23
23
  ```
24
24
 
25
25
  ---
26
+
27
+ ## 1. Strutture Dati e Interfacce (Modelli)
28
+
29
+ Il componente utilizza le seguenti interfacce TypeScript definite in [Models.ts](file:///c:/Users/UTENTE/Desktop/progettoIA/data-table-list/src/model/Models.ts):
30
+
31
+ ```ts
32
+ export interface DataTableConf {
33
+ columns: ColumnTable[]; // Configurazione delle colonne
34
+ actionsRow?: ActionRow; // Azioni di default abilitate per riga
35
+ viewActions: boolean; // Se mostrare o meno la colonna delle azioni
36
+ viewDownload?: boolean; // Se visualizzare il pulsante per il download/esportazione
37
+ paginator?: boolean; // Abilita la paginazione
38
+ paginatorPosition?: PaginatorPosition; // Posizione e allineamento del paginatore
39
+ isserver?: boolean; // Se la paginazione e il filtraggio sono gestiti lato server
40
+ serverPaging?: ServerPaging; // Metadati per la paginazione server-side
41
+ dimensionePagina: number; // Numero di righe per pagina
42
+ messageNotRecords?: string; // Messaggio mostrato se la tabella è vuota
43
+ }
44
+
45
+ export interface ColumnTable {
46
+ title: string; // Intestazione della colonna
47
+ property: string; // Nome della chiave nell'oggetto riga
48
+ style?: string | null; // Stile CSS inline da applicare alla cella (es: "width: 150px")
49
+ callFormatt?: Function | null; // Funzione custom per formattare il valore della cella
50
+ hidden?: boolean; // Nasconde la colonna se impostato a true
51
+ order?: boolean; // Abilita l'ordinamento client-side per questa colonna
52
+ }
53
+
54
+ export interface ActionRow {
55
+ view: boolean; // Mostra l'icona Visualizza (it-password-visible)
56
+ update: boolean; // Mostra l'icona Modifica (it-pencil)
57
+ delete: boolean; // Mostra l'icona Elimina (it-delete)
58
+ }
59
+
60
+ export interface PaginatorPosition {
61
+ top: boolean; // Mostra il paginatore sopra la tabella
62
+ bottom: boolean; // Mostra il paginatore sotto la tabella
63
+ class: string | 'center' | 'left' | 'right'; // Allineamento del paginatore ('left', 'center', 'right')
64
+ }
65
+
66
+ export interface ServerPaging {
67
+ serverTotaleElementi: number; // Numero totale di elementi sul server
68
+ serverTotalePagine: number; // Numero totale di pagine sul server
69
+ }
70
+ ```
71
+
72
+ ---
73
+
74
+ ## 2. API del Componente (Props ed Emits)
75
+
76
+ ### Props (Proprietà)
77
+
78
+ | Nome Prop | Tipo | Obbligatorio | Descrizione |
79
+ | :--- | :--- | :--- | :--- |
80
+ | `dataTableConf` | `DataTableConf` | **Sì** | Configurazione della struttura e del comportamento della tabella. |
81
+ | `dataItems` | `any[]` | **Sì** | Array di dati (righe) da visualizzare. Se `isserver` è `false`, contiene tutti i record. Se `isserver` è `true`, contiene solo i record della pagina corrente. |
82
+ | `filter` | `string` | No | Stringa di ricerca globale. Se specificata e `isserver` è `false`, la tabella esegue un filtro client-side su tutte le colonne visibili. |
83
+ | `showCheckbox` | `boolean` | No | Se impostato a `true`, aggiunge una prima colonna con checkbox per la selezione multipla delle righe. |
84
+
85
+ ### Emits (Eventi)
86
+
87
+ | Nome Evento | Parametri | Descrizione |
88
+ | :--- | :--- | :--- |
89
+ | `@onview` | `(obj: object)` | Emesso al click sul pulsante "Visualizza" della riga (default action). Riceve l'oggetto riga. |
90
+ | `@onupdate` | `(obj: object)` | Emesso al click sul pulsante "Modifica" della riga (default action). Riceve l'oggetto riga. |
91
+ | `@ondelete` | `(obj: object)` | Emesso al click sul pulsante "Elimina" della riga (default action). Riceve l'oggetto riga. |
92
+ | `@onavanti` | `(current: number, size: number)` | Emesso quando si va alla pagina successiva **solo se** `isserver` è `true`. `current` è l'indice di pagina (0-indexed), `size` è la dimensione della pagina. |
93
+ | `@onindietro` | `(current: number, size: number)` | Emesso quando si va alla pagina precedente **solo se** `isserver` è `true`. `current` è l'indice di pagina (0-indexed), `size` è la dimensione della pagina. |
94
+ | `@ondownload` | `(call: any[])` | Emesso al click sul pulsante di download. Riceve la lista corrente dei dati filtrati. |
95
+ | `@onchecked` | `(obj: any[])` | Emesso ogni volta che cambia la selezione delle righe tramite checkbox. Riceve l'array delle righe attualmente selezionate. |
96
+
97
+ ---
98
+
99
+ ## 3. Slot di Personalizzazione
100
+
101
+ `DataTableList` offre diversi slot con scoped-slots per personalizzare profondamente il markup:
102
+
103
+ * **`#columnTd`**: Permette di personalizzare il rendering del contenuto di ogni cella. Riceve `{ row, column }` come parametri dello slot.
104
+ * **`#iconTd`**: Consente di posizionare un'icona o un elemento decorativo a fianco del valore della cella. Riceve `{ row, column }`.
105
+ * **`#actions`**: Sostituisce i pulsanti di default (Visualizza, Modifica, Elimina) con pulsanti personalizzati o menu dropdown. Riceve `{ row }`.
106
+ * **`#checkbox`**: Sostituisce il checkbox di default delle righe. Riceve `{ row }`.
107
+ * **`#download`**: Personalizza l'aspetto del pulsante di download. Riceve l'evento `{ ondownload: { oncall: Function } }`.
108
+
109
+ ---
110
+
111
+ ## 4. Scenari d'Uso ed Esempi di Implementazione
112
+
113
+ ### Scenario A: Tabella Semplice Client-Side con Paginazione e Ordinamento
114
+ In questo scenario, i dati sono interamente caricati in memoria. Il componente gestisce la paginazione, la ricerca globale e l'ordinamento in modo autonomo.
115
+
116
+ ```html
117
+ <script setup lang="ts">
118
+ import { ref } from 'vue';
119
+ import DataTableList from '@/component/commons/DataTableList.vue';
120
+ import type { DataTableConf } from '@/model/Models';
121
+
122
+ const searchFilter = ref('');
123
+
124
+ const tableConfig = ref<DataTableConf>({
125
+ columns: [
126
+ { title: 'ID', property: 'id', order: true },
127
+ { title: 'Nome', property: 'name', order: true },
128
+ { title: 'Email', property: 'email', order: true }
129
+ ],
130
+ isserver: false,
131
+ paginator: true,
132
+ paginatorPosition: { top: true, bottom: true, class: 'right' },
133
+ viewActions: true,
134
+ actionsRow: { view: true, update: true, delete: true },
135
+ dimensionePagina: 5,
136
+ messageNotRecords: 'Nessun utente trovato.'
137
+ });
138
+
139
+ const items = ref([
140
+ { id: 1, name: 'Mario Rossi', email: 'mario.rossi@example.com' },
141
+ { id: 2, name: 'Giuseppe Verdi', email: 'giuseppe.verdi@example.com' },
142
+ { id: 3, name: 'Luca Bianchi', email: 'luca.bianchi@example.com' },
143
+ { id: 4, name: 'Anna Neri', email: 'anna.neri@example.com' },
144
+ { id: 5, name: 'Sofia Gialli', email: 'sofia.gialli@example.com' },
145
+ { id: 6, name: 'Elena Rosa', email: 'elena.rosa@example.com' }
146
+ ]);
147
+
148
+ const handleView = (item: any) => console.log('Visualizza:', item);
149
+ const handleUpdate = (item: any) => console.log('Modifica:', item);
150
+ const handleDelete = (item: any) => console.log('Elimina:', item);
151
+ </script>
152
+
153
+ <template>
154
+ <div class="container my-4">
155
+ <!-- Input di ricerca collegato alla prop :filter -->
156
+ <div class="form-group mb-3">
157
+ <label for="search">Cerca Utente</label>
158
+ <input id="search" v-model="searchFilter" type="text" class="form-control" placeholder="Cerca...">
159
+ </div>
160
+
161
+ <DataTableList
162
+ :data-items="items"
163
+ :data-table-conf="tableConfig"
164
+ :filter="searchFilter"
165
+ @onview="handleView"
166
+ @onupdate="handleUpdate"
167
+ @ondelete="handleDelete"
168
+ />
169
+ </div>
170
+ </template>
171
+ ```
172
+
173
+ ---
174
+
175
+ ### Scenario B: Formattazione Personalizzata di Colonne (`callFormatt`)
176
+ Quando si desidera applicare una formattazione al volo su una colonna (es. date, valute, o composizione stringhe) senza alterare i dati di origine, si può definire la funzione `callFormatt` nel modello `ColumnTable`.
177
+
178
+ ```ts
179
+ const tableConfig = ref<DataTableConf>({
180
+ columns: [
181
+ { title: 'ID', property: 'id' },
182
+ {
183
+ title: 'Nome Completo',
184
+ property: 'name',
185
+ // callFormatt riceve il valore del campo specificato in property e l'intera riga
186
+ callFormatt: (value: any, row: any) => {
187
+ return `${row.name.toUpperCase()} (${row.role})`;
188
+ }
189
+ },
190
+ {
191
+ title: 'Data Creazione',
192
+ property: 'createdAt',
193
+ callFormatt: (value: string) => {
194
+ return new Date(value).toLocaleDateString('it-IT');
195
+ }
196
+ }
197
+ ],
198
+ isserver: false,
199
+ viewActions: false,
200
+ dimensionePagina: 10
201
+ });
202
+
203
+ const items = ref([
204
+ { id: 1, name: 'Mario Rossi', role: 'Admin', createdAt: '2026-06-01T10:00:00Z' },
205
+ { id: 2, name: 'Giuseppe Verdi', role: 'User', createdAt: '2026-06-03T15:30:00Z' }
206
+ ]);
207
+ ```
208
+
209
+ ---
210
+
211
+ ### Scenario C: Personalizzazione Celle con Slot (`#columnTd` & Componenti Custom)
212
+ Se si necessita di inserire markup HTML complesso (es. Badge di stato, icone, o componenti esterni come `Avatar.vue`), si utilizza lo slot `#columnTd`.
213
+
214
+ ```html
215
+ <script setup lang="ts">
216
+ import { ref } from 'vue';
217
+ import { DataTableList, Avatar } from 'data-table-list';
218
+ import type { DataTableConf } from 'data-table-list';
219
+ import 'data-table-list/dist/data-table-list.css';
220
+
221
+ const tableConfig = ref<DataTableConf>({
222
+ columns: [
223
+ { title: 'Avatar', property: 'avatar', style: 'width: 80px;' },
224
+ { title: 'Dettagli Utente', property: 'details' },
225
+ { title: 'Stato', property: 'status' }
226
+ ],
227
+ isserver: false,
228
+ viewActions: false,
229
+ dimensionePagina: 5
230
+ });
231
+
232
+ const items = ref([
233
+ { id: 1, name: 'Mario Rossi', email: 'mario.rossi@example.com', status: 'Attivo', statusColor: 'bg-success' },
234
+ { id: 2, name: 'Giuseppe Verdi', email: 'giuseppe.verdi@example.com', status: 'Sospeso', statusColor: 'bg-warning' }
235
+ ]);
236
+ </script>
237
+
238
+ <template>
239
+ <DataTableList :data-items="items" :data-table-conf="tableConfig">
240
+ <!-- Utilizzo dello scoped slot per le celle -->
241
+ <template #columnTd="{ row, column }">
242
+
243
+ <!-- Cella Avatar -->
244
+ <div v-if="column.property === 'avatar'">
245
+ <Avatar
246
+ :label="row.name.charAt(0) + row.name.split(' ')[1]?.charAt(0)"
247
+ :background-dynamics="true"
248
+ />
249
+ </div>
250
+
251
+ <!-- Cella Dettagli Utente -->
252
+ <div v-else-if="column.property === 'details'">
253
+ <strong>{{ row.name }}</strong><br>
254
+ <small class="text-secondary">{{ row.email }}</small>
255
+ </div>
256
+
257
+ <!-- Cella Stato -->
258
+ <div v-else-if="column.property === 'status'">
259
+ <span class="badge rounded-pill text-white" :class="row.statusColor">
260
+ {{ row.status }}
261
+ </span>
262
+ </div>
263
+
264
+ </template>
265
+ </DataTableList>
266
+ </template>
267
+ ```
268
+
269
+ ---
270
+
271
+ ### Scenario D: Selezione Multipla con Checkbox e Evento `@onchecked`
272
+ Il componente supporta la selezione di elementi tramite una colonna di checkbox abilitata tramite la prop `:show-checkbox="true"`.
273
+
274
+ ```html
275
+ <script setup lang="ts">
276
+ import { ref } from 'vue';
277
+ import DataTableList from '@/component/commons/DataTableList.vue';
278
+ import type { DataTableConf } from '@/model/Models';
279
+
280
+ const tableConfig = ref<DataTableConf>({
281
+ columns: [
282
+ { title: 'ID', property: 'id' },
283
+ { title: 'Prodotto', property: 'product' }
284
+ ],
285
+ isserver: false,
286
+ viewActions: false,
287
+ dimensionePagina: 10
288
+ });
289
+
290
+ const items = ref([
291
+ { id: 101, product: 'Computer Laptop' },
292
+ { id: 102, product: 'Monitor 4K' },
293
+ { id: 103, product: 'Tastiera Meccanica' }
294
+ ]);
295
+
296
+ const selectedItems = ref<any[]>([]);
297
+
298
+ // Salva gli elementi selezionati nello stato locale
299
+ const handleChecked = (checkedRows: any[]) => {
300
+ selectedItems.value = checkedRows;
301
+ console.log('Prodotti selezionati:', selectedItems.value);
302
+ };
303
+ </script>
304
+
305
+ <template>
306
+ <div class="my-3">
307
+ <DataTableList
308
+ :data-items="items"
309
+ :data-table-conf="tableConfig"
310
+ :show-checkbox="true"
311
+ @onchecked="handleChecked"
312
+ />
313
+
314
+ <div class="mt-3">
315
+ <h5>Elementi selezionati: {{ selectedItems.length }}</h5>
316
+ <ul>
317
+ <li v-for="item in selectedItems" :key="item.id">{{ item.product }}</li>
318
+ </ul>
319
+ </div>
320
+ </div>
321
+ </template>
322
+ ```
323
+
324
+ ---
325
+
326
+ ### Scenario E: Menu Azioni Personalizzato (Dropdown Bootstrap Italia)
327
+ Invece di mostrare i tre pulsanti standard in linea (view, update, delete), è possibile personalizzare la colonna delle azioni inserendo un menu a comparsa (dropdown) in perfetto stile Bootstrap Italia utilizzando lo slot `#actions`.
328
+
329
+ ```html
330
+ <script setup lang="ts">
331
+ import { ref } from 'vue';
332
+ import { DataTableList, Avatar } from 'data-table-list';
333
+ import type { DataTableConf } from 'data-table-list';
334
+ import 'data-table-list/dist/data-table-list.css';
335
+
336
+ const tableConfig = ref<DataTableConf>({
337
+ columns: [
338
+ { title: 'ID', property: 'id' },
339
+ { title: 'Documento', property: 'docName' }
340
+ ],
341
+ isserver: false,
342
+ viewActions: true, // Deve essere true per abilitare la colonna azioni
343
+ dimensionePagina: 10
344
+ });
345
+
346
+ const items = ref([
347
+ { id: 1, docName: 'Fattura_2026_01.pdf' },
348
+ { id: 2, docName: 'Contratto_Firmato.pdf' }
349
+ ]);
350
+
351
+ const scaricaDocumento = (row: any) => console.log('Download', row.docName);
352
+ const archiviaDocumento = (row: any) => console.log('Archivia', row.id);
353
+ </script>
354
+
355
+ <template>
356
+ <DataTableList :data-items="items" :data-table-conf="tableConfig">
357
+ <!-- Personalizzazione colonna azioni tramite slot -->
358
+ <template #actions="{ row }">
359
+ <div class="dropdown dropstart text-center">
360
+ <a class="btn btn-dropdown dropdown-toggle" href="#" role="button" id="dropdownActions" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
361
+ <!-- Icona a tre pallini di Bootstrap Italia -->
362
+ <svg class="icon-expand icon icon-sm icon-secondary">
363
+ <use href="@/assets/svg/sprites.svg#it-more-items"></use>
364
+ </svg>
365
+ </a>
366
+ <div class="dropdown-menu" aria-labelledby="dropdownActions">
367
+ <div class="link-list-wrapper">
368
+ <ul class="link-list">
369
+ <li>
370
+ <a class="dropdown-item list-item" @click.prevent="scaricaDocumento(row)">
371
+ <span>
372
+ <svg class="icon icon-primary" aria-hidden="true">
373
+ <use href="@/assets/svg/sprites.svg#it-download"></use>
374
+ </svg> Scarica
375
+ </span>
376
+ </a>
377
+ </li>
378
+ <li>
379
+ <a class="dropdown-item list-item" @click.prevent="archiviaDocumento(row)">
380
+ <span>
381
+ <svg class="icon icon-primary" aria-hidden="true">
382
+ <use href="@/assets/svg/sprites.svg#it-box"></use>
383
+ </svg> Archivia
384
+ </span>
385
+ </a>
386
+ </li>
387
+ </ul>
388
+ </div>
389
+ </div>
390
+ </div>
391
+ </template>
392
+ </DataTableList>
393
+ </template>
394
+ ```
395
+
396
+ ---
397
+
398
+ ### Scenario F: Paginazione Server-Side (`isserver: true`)
399
+ Se la sorgente dati ha molti elementi, la paginazione deve avvenire sul server.
400
+ * `isserver` deve essere impostato a `true`.
401
+ * È necessario compilare `serverPaging` con i totali di elementi e pagine forniti dalle API.
402
+ * Bisogna ascoltare gli eventi `@onavanti` e `@onindietro` per richiedere la pagina corretta al server e aggiornare l'array `dataItems`.
403
+
404
+ ```html
405
+ <script setup lang="ts">
406
+ import { ref, onMounted } from 'vue';
407
+ import { DataTableList, Avatar } from 'data-table-list';
408
+ import type { DataTableConf } from 'data-table-list';
409
+ import 'data-table-list/dist/data-table-list.css';
410
+
411
+ // Stato locale per i dati e il caricamento
412
+ const items = ref<any[]>([]);
413
+ const loading = ref(false);
414
+
415
+ const tableConfig = ref<DataTableConf>({
416
+ columns: [
417
+ { title: 'ID', property: 'id' },
418
+ { title: 'Descrizione', property: 'description' }
419
+ ],
420
+ isserver: true, // Indica che paginazione e ricerca avvengono sul server
421
+ paginator: true,
422
+ paginatorPosition: { top: false, bottom: true, class: 'center' },
423
+ viewActions: false,
424
+ dimensionePagina: 10,
425
+ serverPaging: {
426
+ serverTotaleElementi: 0, // Inizializzato a 0, popolato in seguito
427
+ serverTotalePagine: 0
428
+ }
429
+ });
430
+
431
+ // Funzione simulata per caricare i dati dalle API
432
+ const fetchApiData = async (page: number, size: number) => {
433
+ loading.value = true;
434
+ try {
435
+ // Es. const res = await axios.get(`/api/items?page=${page}&size=${size}`);
436
+ await new Promise((resolve) => setTimeout(resolve, 400));
437
+
438
+ const mockTotalElements = 50;
439
+ const mockTotalPages = Math.ceil(mockTotalElements / size);
440
+
441
+ // Creazione dati simulati per la pagina corrente (es. pagina 0 -> ID 1-10)
442
+ const rows = [];
443
+ const start = page * size;
444
+ for (let i = 0; i < size; i++) {
445
+ const id = start + i + 1;
446
+ if (id <= mockTotalElements) {
447
+ rows.push({ id, description: `Elemento server ${id}` });
448
+ }
449
+ }
450
+
451
+ items.value = rows;
452
+
453
+ // Aggiornamento dei metadati di paginazione server-side
454
+ tableConfig.value.serverPaging = {
455
+ serverTotaleElementi: mockTotalElements,
456
+ serverTotalePagine: mockTotalPages
457
+ };
458
+ } finally {
459
+ loading.value = false;
460
+ }
461
+ };
462
+
463
+ // Gestione del cambio pagina in avanti
464
+ const handleAvanti = async (currentPage: number, size: number) => {
465
+ await fetchApiData(currentPage, size);
466
+ };
467
+
468
+ // Gestione del cambio pagina all'indietro
469
+ const handleIndietro = async (currentPage: number, size: number) => {
470
+ await fetchApiData(currentPage, size);
471
+ };
472
+
473
+ onMounted(async () => {
474
+ // Caricamento iniziale
475
+ await fetchApiData(0, tableConfig.value.dimensionePagina);
476
+ });
477
+ </script>
478
+
479
+ <template>
480
+ <div class="container my-4">
481
+ <h3>Paginazione Server-Side</h3>
482
+ <div v-if="loading" class="alert alert-info">Caricamento...</div>
483
+
484
+ <DataTableList
485
+ :data-items="items"
486
+ :data-table-conf="tableConfig"
487
+ @onavanti="handleAvanti"
488
+ @onindietro="handleIndietro"
489
+ />
490
+ </div>
491
+ </template>
492
+ ```
493
+
494
+ ---
495
+
496
+ ### Scenario G: Esportazione e Download dei Dati Filtrati
497
+ Il componente offre la possibilità di abilitare un pulsante per il download dei dati.
498
+ * Impostare `viewDownload: true` nella configurazione `DataTableConf`.
499
+ * Ascoltare l'evento `@ondownload`, che riceve la lista dei record attualmente filtrati dalla ricerca globale (`filterComputer`).
500
+
501
+ ```html
502
+ <script setup lang="ts">
503
+ import { ref } from 'vue';
504
+ import { DataTableList, Avatar } from 'data-table-list';
505
+ import type { DataTableConf } from 'data-table-list';
506
+ import 'data-table-list/dist/data-table-list.css';
507
+
508
+ const searchFilter = ref('');
509
+
510
+ const tableConfig = ref<DataTableConf>({
511
+ columns: [
512
+ { title: 'ID', property: 'id' },
513
+ { title: 'Nome', property: 'name' }
514
+ ],
515
+ isserver: false,
516
+ viewActions: false,
517
+ viewDownload: true, // Mostra l'icona per il download in alto a destra
518
+ dimensionePagina: 10
519
+ });
520
+
521
+ const items = ref([
522
+ { id: 1, name: 'Mario Rossi' },
523
+ { id: 2, name: 'Giuseppe Verdi' },
524
+ { id: 3, name: 'Luca Bianchi' }
525
+ ]);
526
+
527
+ // Funzione di esportazione CSV client-side al click sul download
528
+ const handleDownload = (filteredData: any[]) => {
529
+ const csvHeaders = 'ID,Nome\n';
530
+ const csvRows = filteredData.map(item => `${item.id},"${item.name}"`).join('\n');
531
+ const csvContent = 'data:text/csv;charset=utf-8,' + csvHeaders + csvRows;
532
+
533
+ const encodedUri = encodeURI(csvContent);
534
+ const link = document.createElement('a');
535
+ link.setAttribute('href', encodedUri);
536
+ link.setAttribute('download', 'esportazione_tabella.csv');
537
+ document.body.appendChild(link);
538
+ link.click();
539
+ document.body.removeChild(link);
540
+ };
541
+ </script>
542
+
543
+ <template>
544
+ <div class="container my-4">
545
+ <div class="form-group mb-3">
546
+ <input v-model="searchFilter" type="text" class="form-control" placeholder="Cerca...">
547
+ </div>
548
+
549
+ <DataTableList
550
+ :data-items="items"
551
+ :data-table-conf="tableConfig"
552
+ :filter="searchFilter"
553
+ @ondownload="handleDownload"
554
+ />
555
+ </div>
556
+ </template>
557
+ ```
558
+
559
+ ---
560
+
561
+ ## 5. Dettagli Implementativi Importanti
562
+
563
+ 1. **Identificativi Checkbox (`checkId`)**: Quando viene attivata la funzionalità checkbox (`showCheckbox = true`), il componente genera temporaneamente la chiave `checkId` all'interno dei record dell'array `dataItems` per identificare univocamente le righe selezionate. L'array restituito dall'evento `@onchecked` conterrà questi campi aggiuntivi.
564
+ 2. **Reset dell'Ordinamento al cambio pagina**: Ad ogni navigazione di pagina (avanti o indietro) o reset del filtro di ricerca, viene richiamata la funzione `resetClassOrder()` che rimuove la classe CSS `.icon-primaryOrder` dall'header della colonna ordinata, indicando che la nuova pagina mostra i dati nel loro stato originario.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "data-table-list",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/data-table-list.umd.cjs",
@@ -32,9 +32,7 @@
32
32
  "vue-router": "^4.6.4"
33
33
  },
34
34
  "peerDependencies": {
35
- "bootstrap-italia": "^2.18.1",
36
- "vue": "^3.5.32",
37
- "vue-router": "^4.6.4"
35
+ "vue": "^3.5.32"
38
36
  },
39
37
  "devDependencies": {
40
38
  "@microsoft/api-extractor": "^7.58.7",
@@ -51,5 +49,6 @@
51
49
  },
52
50
  "engines": {
53
51
  "node": "^20.19.0 || >=22.12.0"
54
- }
52
+ },
53
+ "license": "MIT"
55
54
  }