Skip to main content

Toast Service

Il servizio TessToastService fornisce un'interfaccia unificata per mostrare notifiche toast attraverso diversi UI Kit (PrimeNG, Bootstrap, Material).

Panoramica

TessToastService è UI-agnostic e utilizza il pattern Adapter per delegare l'implementazione al UI Kit configurato nell'applicazione.

Caratteristiche

  • UI-agnostic: Funziona con PrimeNG, Bootstrap, Material
  • Type-safe: Supporto TypeScript completo
  • Auto-dismiss: Chiusura automatica configurabile
  • Severità multiple: Success, Info, Warning, Error
  • Posizionamento: Top, Bottom, Left, Right, Center
  • Sticky messages: Toast persistenti che richiedono chiusura manuale

Installazione

import { provideTessUiLibrary } from '@tess-ui-library/core';

export const appConfig: ApplicationConfig = {
providers: [
provideTessUiLibrary({
uiKit: 'primeng', // o 'bootstrap', 'material'
}),
],
};

Uso Base

Importa il Servizio

import { Component, inject } from '@angular/core';
import { TessToastService } from '@tess-ui-library/core';

@Component({
selector: 'app-example',
standalone: true,
template: `
<button (click)="showSuccess()">Mostra Successo</button>
`,
})
export class ExampleComponent {
private toastService = inject(TessToastService);

showSuccess() {
this.toastService.success('Operazione completata con successo!');
}
}

API

Metodi di Severità

success(message: string, title?: string, options?: ToastOptions): void

Mostra un toast di successo.

this.toastService.success('Utente salvato con successo!', 'Successo');

info(message: string, title?: string, options?: ToastOptions): void

Mostra un toast informativo.

this.toastService.info('Hai 3 nuove notifiche', 'Informazione');

warn(message: string, title?: string, options?: ToastOptions): void

Mostra un toast di warning.

this.toastService.warn('Connessione instabile', 'Attenzione');

error(message: string, title?: string, options?: ToastOptions): void

Mostra un toast di errore.

this.toastService.error('Impossibile salvare i dati', 'Errore');

Metodo Generico

show(message: ToastMessage): void

Mostra un toast con configurazione completa.

this.toastService.show({
severity: 'success',
summary: 'Operazione Completata',
detail: 'I tuoi dati sono stati salvati correttamente',
life: 5000,
sticky: false,
closable: true,
});

ToastMessage Interface

interface ToastMessage {
severity: 'success' | 'info' | 'warn' | 'error';
summary?: string; // Titolo del toast
detail: string; // Messaggio del toast
life?: number; // Durata in ms (default: 3000)
sticky?: boolean; // Se true, richiede chiusura manuale
closable?: boolean; // Mostra pulsante chiusura (default: true)
key?: string; // Identificatore per toast multipli
data?: any; // Dati custom
icon?: string; // Icona personalizzata
styleClass?: string; // CSS class personalizzata
}

ToastOptions Interface

interface ToastOptions {
life?: number; // Durata in ms
sticky?: boolean; // Toast persistente
closable?: boolean; // Mostra pulsante chiusura
key?: string; // Key per posizionamento
}

Gestione Toast

clear(key?: string): void

Rimuove tutti i toast o solo quelli con una specifica key.

// Rimuovi tutti i toast
this.toastService.clear();

// Rimuovi solo toast con key specifica
this.toastService.clear('notifications');

Esempi

Toast di Successo Base

saveUser() {
this.userService.save(this.user).subscribe({
next: () => {
this.toastService.success(
'Utente salvato con successo!',
'Operazione Completata'
);
},
error: (error) => {
this.toastService.error(
'Impossibile salvare l\'utente',
'Errore'
);
}
});
}

Toast con Durata Personalizzata

this.toastService.success(
'File caricato correttamente',
'Upload Completato',
{ life: 5000 } // 5 secondi
);

Toast Sticky (Persistente)

this.toastService.show({
severity: 'warn',
summary: 'Aggiornamento Disponibile',
detail: 'È disponibile una nuova versione dell\'applicazione. Ricarica la pagina per aggiornarla.',
sticky: true,
closable: true,
});

Toast Senza Chiusura Manuale

this.toastService.show({
severity: 'info',
summary: 'Caricamento',
detail: 'Elaborazione in corso...',
closable: false,
life: 10000,
});

Toast Multipli con Key

// Toast per notifiche generali
this.toastService.show({
key: 'main',
severity: 'success',
summary: 'Successo',
detail: 'Operazione completata',
});

// Toast per notifiche secondarie (posizione diversa)
this.toastService.show({
key: 'secondary',
severity: 'info',
summary: 'Info',
detail: 'Nuova notifica',
});

// Rimuovi solo toast main
this.toastService.clear('main');

Toast con Dettagli Errore

deleteUser(userId: string) {
this.userService.delete(userId).subscribe({
next: () => {
this.toastService.success('Utente eliminato', 'Successo');
},
error: (error) => {
this.toastService.show({
severity: 'error',
summary: 'Errore Eliminazione',
detail: error.message || 'Si è verificato un errore imprevisto',
life: 7000,
closable: true,
});
}
});
}

Toast di Conferma con Azione

undoDelete() {
this.toastService.show({
severity: 'success',
summary: 'Elemento Eliminato',
detail: 'L\'elemento è stato eliminato. Clicca qui per annullare.',
sticky: true,
data: { action: 'undo', itemId: this.deletedItemId },
});
}

// Nel componente toast-container (custom)
onToastClick(message: ToastMessage) {
if (message.data?.action === 'undo') {
this.restoreItem(message.data.itemId);
this.toastService.clear();
}
}

Toast per Operazioni Lunghe

async processLargeFile() {
// Mostra toast di inizio
this.toastService.info(
'Elaborazione del file in corso...',
'Attendere',
{ closable: false, life: 0 }
);

try {
await this.fileService.process(this.file);

// Rimuovi toast di loading
this.toastService.clear();

// Mostra toast di successo
this.toastService.success(
'File elaborato con successo!',
'Completato'
);
} catch (error) {
this.toastService.clear();
this.toastService.error(
'Errore durante l\'elaborazione del file',
'Errore'
);
}
}

Toast con HTTP Interceptor

import { HttpInterceptorFn } from '@angular/common/http';
import { inject } from '@angular/core';
import { TessToastService } from '@tess-ui-library/core';
import { catchError } from 'rxjs/operators';

export const errorInterceptor: HttpInterceptorFn = (req, next) => {
const toastService = inject(TessToastService);

return next(req).pipe(
catchError((error) => {
// Mostra toast per errori HTTP
if (error.status >= 500) {
toastService.error(
'Si è verificato un errore del server',
'Errore Server'
);
} else if (error.status === 401) {
toastService.warn(
'Sessione scaduta. Effettua nuovamente l\'accesso.',
'Autenticazione Richiesta'
);
} else if (error.status === 403) {
toastService.warn(
'Non hai i permessi per eseguire questa operazione',
'Accesso Negato'
);
}

throw error;
})
);
};

Posizionamento (UI Kit Specifico)

PrimeNG

Con PrimeNG, usa il componente p-toast nel tuo template principale:

<!-- app.component.html -->
<p-toast key="main"></p-toast>
<p-toast key="secondary" position="bottom-right"></p-toast>

<router-outlet></router-outlet>

Posizioni disponibili:

  • top-left
  • top-center
  • top-right
  • bottom-left
  • bottom-center
  • bottom-right

Bootstrap

Con Bootstrap, aggiungi il container nel template principale:

<!-- app.component.html -->
<ngb-toast-container class="toast-container position-fixed top-0 end-0 p-3"></ngb-toast-container>

<router-outlet></router-outlet>

Material

Con Material, usa MatSnackBar che è già configurato:

// Nessun template aggiuntivo necessario

Configurazione Globale

Configura il comportamento di default dei toast:

// app.config.ts
import { provideTessUiLibrary, TOAST_CONFIG } from '@tess-ui-library/core';

export const appConfig: ApplicationConfig = {
providers: [
provideTessUiLibrary({ uiKit: 'primeng' }),
{
provide: TOAST_CONFIG,
useValue: {
life: 4000, // Durata default 4 secondi
sticky: false, // Non sticky per default
closable: true, // Sempre chiudibile
position: 'top-right', // Posizione default
},
},
],
};

Best Practices

  1. Usa severità appropriate: Success per azioni completate, error per errori, warn per avvisi, info per notifiche
  2. Messaggi chiari e concisi: Evita messaggi lunghi, usa il detail per informazioni aggiuntive
  3. Durata appropriata:
    • Success/Info: 3-4 secondi
    • Warning: 5-7 secondi
    • Error: 7-10 secondi o sticky
  4. Evita toast multipli: Usa clear() prima di mostrare un nuovo toast importante
  5. Sticky solo quando necessario: Usa sticky solo per messaggi che richiedono azione o conferma
  6. Accessibilità: I toast devono essere leggibili da screen reader (già implementato)
  7. Non abusare: Usa i toast per feedback immediato, non per conversazioni complesse

Vedi Anche