@esfaenza/tabber
v20.3.24
Published
Libreria che rende disponibile un componente standard per gestire una visualizzazione a tab con eventuali livelli multipli.
Readme
Tabber
Libreria che rende disponibile un componente standard per gestire una visualizzazione a tab con eventuali livelli multipli.
Installazione
Installazione: npm install @esfaenza/tabber
Dipendenze: Vedere la pagina delle dipendenze
Setup
Per effettuare il Setup della libreria è sufficiente configurarla nel modulo dove si vuole utilizzare o nel modulo Shared da cui renderla disponibile ad eventuali altri moduli:
import { TabberModule } from "@esfaenza/tabber";
...
const MODULES = [
[...],
TabberModule.forRoot({ debugMode: false }),
[...]
];
...
// Se modulo Shared
const MODULES_TO_EXPORT = [
[...],
TabberModule,
[...]
];
...
@NgModule({
imports: [...MODULES, ...MODULES_TO_EXPORT],
declarations: [...],
// Se modulo shared
exports: [[...], ...MODULES_TO_EXPORT]
})
export class Module { }
Utilizzo
Dopo aver effettuato il setup della libreria è possibile utilizzare direttamente il componente:
Di seguito un esempio dell'HTML:
<tab-component [AutoVisited]="true" (onTabSelected)="setupDataForTab($event)">
<div *tab="'TAB1'; Label: 'Sezione 1'; Selected: true;">
<div style="padding: 15px;">
Contenuto Sezione 1
</div>
</div>
<div *tab="'TAB2'; Label: 'Sezione 2'; Selected: false;">
<tab-component [Filled]="false" (onTabSelected)="setupDataForTab($event)">
<div *tab="'TAB2_1'; Label: 'Sezione 2 - A'; Selected: true">
<div style="padding: 15px;">
Contenuto Sezione 2-A
</div>
</div>
<div *tab="'TAB2_2'; Label: 'Sezione 2 - B'">
<div style="padding: 15px;">
Contenuto Sezione 2-B
</div>
</div>
</tab-component>
</div>
<div *tab="'TAB3'; Label: 'Sezione 3'; Selected: false;">
<div style="padding: 15px;">
Contenuto Sezione 3
</div>
</div>
</tab-component>Per poi collegarsi agli eventi di selezione nel TS:
public setupDataForTab(tab: EsTabDirective) {
if (tab.Visited())
return;
switch (tab.Id()) {
case 'TAB1':
console.log("Primo caricamento della TAB 1");
break;
case 'TAB2':
console.log("Primo caricamento della TAB 2");
break;
case 'TAB2_1':
console.log("Primo caricamento della TAB 2-A");
break;
case 'TAB2_2':
console.log("Primo caricamento della TAB 2-B");
break;
case 'TAB3':
console.log("Primo caricamento della TAB 3");
break;
default:
break;
}
}
Il contenuto di una tab viene renderizzato solo la prima volta che la tab viene selezionata (lazy), e da quel
momento resta nel DOM nascosto: lo stato dei componenti interni sopravvive al cambio tab. Il check
if (tab.Visited()) return; serve quindi a caricare i dati una volta sola.
Il vecchio codice scritto con le proprietà non-signal (tab._visited, tab.tab, ...) continua a funzionare:
vedi API a signal.
API a signal
La libreria è interamente basata sui signal: input, output e query sono quelli dell'API moderna di
Angular, e TabComponent gira in ChangeDetectionStrategy.OnPush. I binding nei template
non cambiano ([Filled]="...", *tab="'ID'; Label: '...'", (onTabSelected)="..."): cambia solo il modo
di leggere i valori da TypeScript.
Sul TabComponent:
| Membro | Tipo |
| --- | --- |
| Filled / AutoVisited / LoadEagerly / ModernStyles | InputSignal<boolean> |
| onTabSelected | OutputEmitterRef<EsTabDirective> (ha ancora subscribe()) |
| TabsToShow | Signal<EsTabDirective[]> — tab mostrate, ricalcolate da sole |
Sulla EsTabDirective:
| Signal | Sostituisce | Note |
| --- | --- | --- |
| Id() | tab | |
| Label() | tabLabel | |
| Display() | tabDisplay | Computed: tiene già conto di Enabled/Visible |
| Selected() | tabSelected | model, scrivibile con Selected.set(...) |
| Visited() | _visited | Scrivibile con Visited.set(...) |
| Enabled() / Visible() | tabEnabled / tabVisible | Deprecati |
Le vecchie proprietà restano disponibili come accessor deprecati (anche in scrittura dove lo erano prima,
cioè tabSelected e _visited), quindi il codice esistente che fa switch (tab.tab) o
if (tab._visited) return; continua a funzionare senza modifiche.
API del componente
| Input | Default | Descrizione |
| --- | --- | --- |
| Filled | true | true per un gruppo di tab principali, false per un gruppo di sottotab |
| AutoVisited | true | Marca automaticamente come "visitata" la tab appena selezionata |
| LoadEagerly | false | Renderizza subito il contenuto di tutte le tab invece che al primo accesso |
| ModernStyles | false | Attiva il layout moderno (vedi sotto) |
| Output | Descrizione |
| --- | --- |
| onTabSelected | Emette la EsTabDirective selezionata, sia al primo setup che ad ogni cambio tab |
Sulla singola tab (microsintassi *tab):
| Chiave | Input | Default | Descrizione |
| --- | --- | --- | --- |
| *tab="'ID'" | tab | — | Identificativo della tab, quello che arriva in onTabSelected |
| Label | tabLabel | — | Etichetta mostrata nell'intestazione |
| Selected | tabSelected | false | Tab selezionata all'avvio (una sola per gruppo, altrimenti il componente lancia un errore) |
| Display | tabDisplay | "Full" | Full mostra la tab, Disabled la mostra non selezionabile, Hidden occupa spazio senza mostrarla, None la esclude dal gruppo |
| Enabled | tabEnabled | true | Deprecato: false equivale a Display: 'Disabled' |
| Visible | tabVisible | true | Deprecato: false equivale a Display: 'None' |
La lista delle tab può cambiare dopo il primo render (es. *ngFor su dati caricati in asincrono): il gruppo si
riallinea da solo, senza riemettere la selezione se la tab corrente è ancora presente.
Layout moderno
[ModernStyles]="true" applica la classe es-tabber-modern sull'host e attiva un layout rinfrescato
(header a pill con indicatore attivo, sottotab arrotondate, spinner di caricamento in puro CSS senza
dipendenza da FontAwesome). Il markup non cambia: con l'input a false, default, la resa è identica a
quella storica.
<tab-component [ModernStyles]="true">
...
</tab-component>Il layout moderno distribuisce le tab in flex, quindi regge un numero qualsiasi di tab: il limite di 10 tab principali / 5 sottotab riguarda solo le classi di larghezza del layout storico.
Non si propaga alle tab annidate: va impostato anche sul tab-component interno.
Personalizzazione dei colori
I colori sono CSS custom properties, valorizzabili su un qualsiasi antenato (vengono ereditate e attraversano la view encapsulation):
tab-component {
--es-tabber-accent: #e91e63;
}| Custom property | Default | Uso |
| --- | --- | --- |
| --es-tabber-accent | #344154 | Colore della tab attiva, dell'indicatore e delle pill delle sottotab |
| --es-tabber-accent-strong | #242d3a | Variante scura per gli hover |
| --es-tabber-hover | rgba(17, 24, 39, 0.06) | Sfondo in hover sulle tab non attive |
| --es-tabber-text | #111827 | Colore del testo |
| --es-tabber-muted | #6b7280 | Testo delle tab non attive e disabilitate |
| --es-tabber-border | #d1d5db | Bordi e traccia dello spinner |
| --es-tabber-surface | #ffffff | Sfondo della tab attiva e del contenuto |
| --es-tabber-surface-muted | #f3f4f6 | Sfondo delle tab disabilitate |
| --es-tabber-radius | 10px | Raggio degli angoli degli header |
