toast-message-display
v18.0.5
Published
This is an Angular Module containing Components/Services using Material
Readme
Toast Message Display Service
Overview
The toast-message-display library provides a comprehensive notification service for displaying toast messages with customizable styling and behavior. Built on Angular Material's SnackBar, it offers a robust queuing system, predefined color themes, flexible positioning, and action button support for creating professional user feedback experiences.
Core Capabilities
🔔 Advanced Toast Notification System
- Message Queuing: Automatically queues multiple toasts and displays them sequentially
- Six Color Themes: Predefined color schemes for different message types (SUCCESS, ERROR, INFO, WARN, NOTIFY, GENERAL)
- Flexible Positioning: Top or bottom positioning with configurable alignment
- Action Support: Optional action buttons with custom dismissal timing
- Icon Integration: Material icons displayed alongside messages
- Duration Control: Automatic or manual dismissal with configurable timing
- Service-based Architecture: Easy injection and usage throughout applications
🔧 Features
✅ Message Queuing - Sequential display of multiple toast messages
✅ Six Color Themes - SUCCESS (green), ERROR (red), INFO (blue), WARN (yellow), NOTIFY (dark grey), GENERAL (light grey)
✅ Flexible Positioning - Top or bottom alignment
✅ Action Buttons - Optional action buttons with custom text
✅ Icon Support - Material icons alongside messages
✅ Duration Control - Configurable auto-dismiss timing
✅ Service Integration - Easy injection throughout applications
✅ Queue Management - Handles multiple simultaneous requests
Key Benefits
| Feature | Description | |---------|-------------| | Professional UI | Material Design based toast notifications | | Message Queuing | Handles multiple messages gracefully | | Theme Support | Six predefined color themes for different message types | | Flexible Positioning | Top or bottom positioning options | | Action Support | Interactive action buttons with custom handlers | | Icon Integration | Visual icons for better message recognition |
Summary
The toast-message-display library provides a professional notification system for Angular applications, offering comprehensive message queuing, theming, and interaction capabilities built on Angular Material's foundation.
Quick Start Guide
Installation & Setup (2 minutes)
1. Import Module
// app.module.ts
import { ToastMessageDisplayModule } from 'toast-message-display';
@NgModule({
imports: [
ToastMessageDisplayModule
]
})
export class AppModule { }2. Dependencies
The package integrates with Angular Material:
npm install @angular/material @angular/cdkQuick Examples
Example 1: Basic Success Message
import { Component, inject } from '@angular/core';
import { ToastMessageDisplayService } from 'toast-message-display';
import { ToastDisplay, ToastColors } from 'toast-message-display';
@Component({
selector: 'app-success-example',
template: `
<button (click)="showSuccess()">Show Success Message</button>
`
})
export class SuccessExampleComponent {
private toastService = inject(ToastMessageDisplayService);
showSuccess() {
const display = ToastDisplay.adapt({
message: 'Data saved successfully!',
action: 'OK',
color: ToastColors.SUCCESS,
icon: 'check_circle'
});
this.toastService.toastMessageDisplay(display, 3000);
}
}Example 2: Error Message with Custom Duration
import { Component, inject } from '@angular/core';
import { ToastMessageDisplayService } from 'toast-message-display';
import { ToastDisplay, ToastColors, VerticalAlignment } from 'toast-message-display';
@Component({
selector: 'app-error-example',
template: `
<button (click)="showError()">Show Error Message</button>
`
})
export class ErrorExampleComponent {
private toastService = inject(ToastMessageDisplayService);
showError() {
const display = ToastDisplay.adapt({
message: 'Failed to save data. Please try again.',
action: 'Retry',
color: ToastColors.ERROR,
icon: 'error'
});
// Show for 5 seconds at the bottom
this.toastService.toastMessageDisplay(display, 5000, VerticalAlignment.BOTTOM);
}
}Example 3: Information Message
import { Component, inject } from '@angular/core';
import { ToastMessageDisplayService } from 'toast-message-display';
import { ToastDisplay, ToastColors } from 'toast-message-display';
@Component({
selector: 'app-info-example',
template: `
<button (click)="showInfo()">Show Info Message</button>
`
})
export class InfoExampleComponent {
private toastService = inject(ToastMessageDisplayService);
showInfo() {
const display = ToastDisplay.adapt({
message: 'Your profile has been updated successfully.',
color: ToastColors.INFO,
icon: 'info'
});
this.toastService.toastMessageDisplay(display);
}
}Example 4: Warning Message with Action
import { Component, inject } from '@angular/core';
import { ToastMessageDisplayService } from 'toast-message-display';
import { ToastDisplay, ToastColors } from 'toast-message-display';
@Component({
selector: 'app-warning-example',
template: `
<button (click)="showWarning()">Show Warning</button>
`
})
export class WarningExampleComponent {
private toastService = inject(ToastMessageDisplayService);
showWarning() {
const display = ToastDisplay.adapt({
message: 'You have unsaved changes. Do you want to save?',
action: 'Save',
color: ToastColors.WARN,
icon: 'warning'
});
this.toastService.toastMessageDisplay(display, 0); // 0 = manual dismiss only
}
}Example 5: Multiple Sequential Messages
import { Component, inject } from '@angular/core';
import { ToastMessageDisplayService } from 'toast-message-display';
import { ToastDisplay, ToastColors } from 'toast-message-display';
@Component({
selector: 'app-sequence-example',
template: `
<button (click)="showSequence()">Show Message Sequence</button>
`
})
export class SequenceExampleComponent {
private toastService = inject(ToastMessageDisplayService);
showSequence() {
// These will be queued and displayed sequentially
const messages = [
{
message: 'Starting process...',
color: ToastColors.INFO,
icon: 'hourglass_empty'
},
{
message: 'Processing data...',
color: ToastColors.INFO,
icon: 'process'
},
{
message: 'Process completed successfully!',
color: ToastColors.SUCCESS,
icon: 'check_circle'
}
];
messages.forEach((msg, index) => {
setTimeout(() => {
const display = ToastDisplay.adapt(msg);
this.toastService.toastMessageDisplay(display, 2000);
}, index * 2500); // Stagger the messages
});
}
}Example 6: Notification Center Pattern
import { Component, inject } from '@angular/core';
import { ToastMessageDisplayService } from 'toast-message-display';
import { ToastDisplay, ToastColors } from 'toast-message-display';
@Component({
selector: 'app-notification-center',
template: `
<div class="notification-controls">
<button (click)="notifySuccess()">Success</button>
<button (click)="notifyError()">Error</button>
<button (click)="notifyWarning()">Warning</button>
<button (click)="notifyInfo()">Info</button>
<button (click)="notifyCustom()">Custom</button>
</div>
`,
styles: [`
.notification-controls {
display: flex;
gap: 1rem;
flex-wrap: wrap;
}
button {
padding: 0.5rem 1rem;
border: none;
border-radius: 4px;
cursor: pointer;
}
`]
})
export class NotificationCenterComponent {
private toastService = inject(ToastMessageDisplayService);
notifySuccess() {
const display = ToastDisplay.adapt({
message: 'Operation completed successfully!',
action: 'View',
color: ToastColors.SUCCESS,
icon: 'check_circle'
});
this.toastService.toastMessageDisplay(display);
}
notifyError() {
const display = ToastDisplay.adapt({
message: 'An error occurred while processing your request.',
action: 'Retry',
color: ToastColors.ERROR,
icon: 'error'
});
this.toastService.toastMessageDisplay(display, 0); // Manual dismiss
}
notifyWarning() {
const display = ToastDisplay.adapt({
message: 'Your session will expire in 5 minutes.',
action: 'Extend',
color: ToastColors.WARN,
icon: 'schedule'
});
this.toastService.toastMessageDisplay(display, 10000);
}
notifyInfo() {
const display = ToastDisplay.adapt({
message: 'New features are available. Check them out!',
color: ToastColors.INFO,
icon: 'new_releases'
});
this.toastService.toastMessageDisplay(display, 4000);
}
notifyCustom() {
const display = ToastDisplay.adapt({
message: 'Custom notification with your own styling',
action: 'Details',
color: ToastColors.NOTIFY,
icon: 'notifications'
});
this.toastService.toastMessageDisplay(display);
}
}Service API
ToastMessageDisplayService
Methods
toastMessageDisplay(display: ToastDisplay, duration?: number, alignment?: VerticalAlignment): void
Displays a toast message with the specified configuration.
Parameters:
display: ToastDisplay- Configuration object for the toast messageduration?: number- Duration in milliseconds (0 = manual dismiss only)alignment?: VerticalAlignment- Position alignment (TOP or BOTTOM)
Example:
const display = ToastDisplay.adapt({
message: 'Hello World!',
action: 'OK',
color: ToastColors.SUCCESS,
icon: 'info'
});
this.toastService.toastMessageDisplay(display, 3000, VerticalAlignment.TOP);Model Structures
ToastDisplay
export interface ToastDisplayInterface {
message: string; // Required: The message text to display
action?: string; // Optional: Action button text
color?: ToastColors; // Optional: Color theme
icon?: string; // Optional: Material icon name
}
export class ToastDisplay implements ToastDisplayInterface {
constructor(
public message: string,
public action?: string,
public color?: ToastColors,
public icon?: string,
) {}
static adapt(item?: any): ToastDisplay {
return new ToastDisplay(
item?.message,
item?.action,
item?.color,
item?.icon,
);
}
}ToastColors Enum
export enum ToastColors {
SUCCESS = "#006B31", // Green
ERROR = "#CC0000", // Red
INFO = "#02559F", // Blue
WARN = "#FFC20E", // Yellow
NOTIFY = "#080808", // Dark Grey
GENERAL = "#f5f5f5" // Light Grey
}VerticalAlignment Enum
export enum VerticalAlignment {
TOP = "top", // Display at the top of the screen
BOTTOM = "bottom" // Display at the bottom of the screen
}Usage Examples
// Basic message configuration
const basicMessage = ToastDisplay.adapt({
message: 'This is a basic message'
});
// Full configuration
const fullMessage = ToastDisplay.adapt({
message: 'Complete configuration with all options',
action: 'Click Me',
color: ToastColors.SUCCESS,
icon: 'check_circle'
});
// String-based configuration (backward compatibility)
const stringMessage = ToastDisplay.adapt('Simple string message');Configuration Options
ToastDisplay Configuration
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| message | string | The text message to display in the toast | Yes |
| action | string | Optional action button text | No |
| color | ToastColors | Color theme for the toast | No |
| icon | string | Material icon name to display | No |
Display Method Options
| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
| display | ToastDisplay | Toast configuration object | Required |
| duration | number | Duration in milliseconds (0 = manual) | 3000 |
| alignment | VerticalAlignment | Top or bottom positioning | TOP |
Color Themes
| Color | Hex Value | Use Case | Example |
|-------|-----------|----------|---------|
| SUCCESS | #006B31 | Success messages, confirmations | "Data saved successfully" |
| ERROR | #CC0000 | Error messages, failures | "Failed to save data" |
| INFO | #02559F | Informational messages | "New features available" |
| WARN | #FFC20E | Warning messages | "Session expires soon" |
| NOTIFY | #080808 | General notifications | "Settings updated" |
| GENERAL | #f5f5f5 | Default/neutral messages | "Processing..." |
Module Configuration
ToastMessageDisplayModule
No Global Configuration Required
The ToastMessageDisplayModule does not provide a forRoot() method or global configuration options. All configuration is done at the service level through method parameters.
Module Structure
@NgModule({
declarations: [
ToastUIComponent,
ToastMessageInlineComponent,
],
imports: [
// Dependencies are handled by Angular Material
],
exports: [
ToastUIComponent,
ToastMessageInlineComponent,
]
})
export class ToastMessageDisplayModule { }Dependencies
- @angular/material: Material Design components (SnackBar)
- @angular/cdk: Component Development Kit
- @angular/common: Core Angular functionality
Advanced Usage Patterns
Integration with HTTP Request Manager
import { Component, inject } from '@angular/core';
import { ToastMessageDisplayService } from 'toast-message-display';
import { HTTPManagerService } from 'http-request-manager';
import { ToastDisplay, ToastColors } from 'toast-message-display';
@Component({
selector: 'app-http-integration',
template: `
<button (click)="saveData()">Save Data</button>
`
})
export class HttpIntegrationComponent {
private toastService = inject(ToastMessageDisplayService);
private httpManager = inject(HTTPManagerService);
saveData() {
// Show loading toast
const loadingToast = ToastDisplay.adapt({
message: 'Saving data...',
color: ToastColors.INFO,
icon: 'hourglass_empty'
});
this.toastService.toastMessageDisplay(loadingToast);
// Make HTTP request
this.httpManager.postRequest({
path: ['api', 'data'],
body: { data: 'sample' }
}).subscribe({
next: (response) => {
// Show success toast
const successToast = ToastDisplay.adapt({
message: 'Data saved successfully!',
action: 'View',
color: ToastColors.SUCCESS,
icon: 'check_circle'
});
this.toastService.toastMessageDisplay(successToast);
},
error: (error) => {
// Show error toast
const errorToast = ToastDisplay.adapt({
message: 'Failed to save data. Please try again.',
action: 'Retry',
color: ToastColors.ERROR,
icon: 'error'
});
this.toastService.toastMessageDisplay(errorToast, 0);
}
});
}
}Toast Queue Management
import { Component, inject } from '@angular/core';
import { ToastMessageDisplayService } from 'toast-message-display';
import { ToastDisplay, ToastColors } from 'toast-message-display';
@Component({
selector: 'app-queue-management',
template: `
<div class="queue-controls">
<button (click)="addToQueue()">Add to Queue</button>
)="clearQueue()">Clear All</button>
</div>
`
})
export class QueueManagementComponent {
private toastService = <button (click inject(ToastMessageDisplayService);
private messageCount = 0;
addToQueue() {
this.messageCount++;
const message = ToastDisplay.adapt({
message: `Queued message #${this.messageCount}`,
action: 'Dismiss',
color: ToastColors.INFO,
icon: 'queue'
});
// All messages go to the same queue
this.toastService.toastMessageDisplay(message, 2000);
}
clearQueue() {
// Messages are automatically cleared when dismissed
// For immediate clearing, you might need to implement custom logic
console.log('Queue will clear as messages are dismissed');
}
}Custom Toast Factory
import { Component, inject } from '@angular/core';
import { ToastMessageDisplayService } from 'toast-message-display';
import { ToastDisplay, ToastColors } from 'toast-message-display';
@Component({
selector: 'app-toast-factory',
template: `
<button (click)="showUserMessage('success')">Success</button>
<button (click)="showUserMessage('error')">Error</button>
<button (click)="showUserMessage('warning')">Warning</button>
`
})
export class ToastFactoryComponent {
private toastService = inject(ToastMessageDisplayService);
showUserMessage(type: 'success' | 'error' | 'warning') {
const configs = {
success: {
message: 'Operation completed successfully!',
color: ToastColors.SUCCESS,
icon: 'check_circle',
action: 'Great!'
},
error: {
message: 'An error occurred. Please try again.',
color: ToastColors.ERROR,
icon: 'error',
action: 'Retry'
},
warning: {
message: 'Please review your input before proceeding.',
color: ToastColors.WARN,
icon: 'warning',
action: 'Review'
}
};
const config = configs[type];
const display = ToastDisplay.adapt(config);
this.toastService.toastMessageDisplay(display);
}
}Styling and Customization
CSS Customization
While the component uses Material Design styling, you can customize the appearance:
// Custom toast styling
.mat-snack-bar-container {
&.custom-toast {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
.mat-button {
color: white;
&:hover {
background: rgba(255, 255, 255, 0.1);
}
}
}
}Theme Integration
// Integrate with Angular Material theme
@use '@angular/material' as mat;
$custom-palette: (
toast-success: #006B31,
toast-error: #CC0000,
toast-info: #02559F,
toast-warning: #FFC20E
);
@include mat.core();Best Practices
Message Guidelines
- Keep messages concise: Use short, clear messages
- Use appropriate colors: Match message type to color theme
- Provide meaningful actions: Action buttons should be actionable
- Set appropriate durations: Longer for important messages, shorter for notifications
- Queue management: Let the system handle multiple messages gracefully
Performance Considerations
- Avoid excessive queuing: Don't create too many simultaneous toasts
- Use appropriate durations: Manual dismiss for critical errors
- Clean up subscriptions: Ensure proper cleanup in component lifecycle
Accessibility
- Screen reader support: Messages are announced by screen readers
- Keyboard navigation: Action buttons are keyboard accessible
- Color contrast: Ensure sufficient contrast for readability
Integration Examples
With Form Validation
import { Component, inject } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { ToastMessageDisplayService } from 'toast-message-display';
import { ToastDisplay, ToastColors } from 'toast-message-display';
@Component({
selector: 'app-form-with-toasts',
template: `
<form [formGroup]="userForm" (ngSubmit)="onSubmit()">
<input formControlName="email" placeholder="Email">
<input formControlName="name" placeholder="Name">
<button type="submit" [disabled]="userForm.invalid">Submit</button>
</form>
`
})
export class FormWithToastsComponent {
private fb = inject(FormBuilder);
private toastService = inject(ToastMessageDisplayService);
userForm = this.fb.group({
email: ['', [Validators.required, Validators.email]],
name: ['', Validators.required]
});
onSubmit() {
if (this.userForm.valid) {
// Show success message
const successToast = ToastDisplay.adapt({
message: 'Form submitted successfully!',
color: ToastColors.SUCCESS,
icon: 'check_circle'
});
this.toastService.toastMessageDisplay(successToast);
this.userForm.reset();
} else {
// Show validation errors
const errors = [];
if (this.userForm.get('email')?.errors?.['required']) {
errors.push('Email is required');
}
if (this.userForm.get('email')?.errors?.['email']) {
errors.push('Please enter a valid email');
}
if (this.userForm.get('name')?.errors?.['required']) {
errors.push('Name is required');
}
const errorToast = ToastDisplay.adapt({
message: errors.join('. '),
color: ToastColors.ERROR,
icon: 'error'
});
this.toastService.toastMessageDisplay(errorToast, 0);
}
}
}With State Management
import { Component, inject } from '@angular/core';
import { Store } from '@ngrx/store';
import { ToastMessageDisplayService } from 'toast-message-display';
import { ToastDisplay, ToastColors } from 'toast-message-display';
@Component({
selector: 'app-state-integration',
template: `
<div *ngFor="let item of items$ | async">
{{ item.name }}
<button (click)="deleteItem(item.id)">Delete</button>
</div>
`
})
export class StateIntegrationComponent {
private store = inject(Store);
private toastService = inject(ToastMessageDisplayService);
items$ = this.store.select(state => state.items);
deleteItem(id: string) {
this.store.dispatch(deleteItem({ id }));
// Show toast notification
const toast = ToastDisplay.adapt({
message: 'Item deleted successfully',
action: 'Undo',
color: ToastColors.INFO,
icon: 'delete'
});
this.toastService.toastMessageDisplay(toast);
}
}Testing
Unit Testing Example
import { TestBed, inject } from '@angular/core/testing';
import { ToastMessageDisplayService } from './toast-message-display.service';
import { ToastDisplay, ToastColors } from './models/toast-display.model';
describe('ToastMessageDisplayService', () => {
let service: ToastMessageDisplayService;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [ToastMessageDisplayService]
});
});
it('should be created', inject([ToastMessageDisplayService], (service: ToastMessageDisplayService) => {
expect(service).toBeTruthy();
}));
it('should display a basic message', inject([ToastMessageDisplayService], (service: ToastMessageDisplayService) => {
spyOn(service, 'toastMessageDisplay');
const display = ToastDisplay.adapt({
message: 'Test message',
color: ToastColors.SUCCESS,
icon: 'check'
});
service.toastMessageDisplay(display);
expect(service.toastMessageDisplay).toHaveBeenCalledWith(display, 3000, undefined);
}));
it('should handle custom duration', inject([ToastMessageDisplayService], (service: ToastMessageDisplayService) => {
spyOn(service, 'toastMessageDisplay');
const display = ToastDisplay.adapt({ message: 'Test message' });
service.toastMessageDisplay(display, 5000);
expect(service.toastMessageDisplay).toHaveBeenCalledWith(display, 5000, undefined);
}));
});Troubleshooting
Common Issues
- Toast not displaying: Ensure ToastMessageDisplayModule is imported
- Styling issues: Verify Angular Material theme is properly configured
- Action button not working: Check that action text is provided
- Queue not working: Multiple toasts should automatically queue
Debug Mode
@Component({
template: `
<div class="debug-info">
<button (click)="testBasicToast()">Test Basic Toast</button>
<button (click)="testCustomToast()">Test Custom Toast</button>
</div>
`
})
export class ToastDebugComponent {
private toastService = inject(ToastMessageDisplayService);
testBasicToast() {
const display = ToastDisplay.adapt({
message: 'Debug: Basic toast message',
color: ToastColors.INFO,
icon: 'bug_report'
});
this.toastService.toastMessageDisplay(display);
}
testCustomToast() {
const display = ToastDisplay.adapt({
message: 'Debug: Custom configuration',
action: 'Debug Action',
color: ToastColors.WARN,
icon: 'settings'
});
this.toastService.toastMessageDisplay(display, 0); // Manual dismiss
}
}Performance Issues
// Monitor toast queue performance
@Component({
template: `
<div class="performance-monitor">
<p>Active Toasts: {{ activeToastCount }}</p>
<button (click)="stressTest()">Stress Test</button>
</div>
`
})
export class PerformanceMonitorComponent {
activeToastCount = 0;
stressTest() {
// Create multiple toasts to test queue performance
for (let i = 0; i < 10; i++) {
setTimeout(() => {
const display = ToastDisplay.adapt({
message: `Stress test message ${i + 1}`,
color: ToastColors.INFO,
icon: 'speed'
});
this.toastService.toastMessageDisplay(display, 1000);
}, i * 200);
}
}
}