June 25 2017

Angular 2/4 - Alert (Toaster) Notifications

Alert messages (a.k.a. toaster notifications) are an extremely common requirement in web applications for displaying status notifications to the user, status messages can be errors, success messages, warnings or general information.

This tutorial shows how to implement a simple reusable alert / toaster notification service and component in an Angular 2/4 application using TypeScript. The alert component in the example app uses code from a web application I developed recently for a Sydney based law firm, it supports displaying multiple alert notifications at the same time as well as keeping the alerts after a route change, which can be used when you want to display a notification after a route change, for example to display a success message after a users registers an account and is redirected to the login page.

Project code is available on GitHub at https://github.com/cornflourblue/angular2-alert-notifications.


Angular 2/4 Alert / Toaster Notifications Demo

Here's the tutorial example application in action, it includes buttons for displaying the different types of alert / toaster messages, and for clearing the messages.

(See on Plunker at http://plnkr.co/edit/gDrxfK?p=preview)


Running the Angular 2/4 Alert / Toaster Example Locally

  1. Install NodeJS and NPM from https://nodejs.org/en/download/, you can check the versions you have installed by running node -v and npm -v from the command line.
     
  2. Download the project source code from https://github.com/cornflourblue/angular2-alert-notifications
     
  3. Install all required npm packages by running npm install from the command line in the project root folder (where the package.json is located).
     
  4. Start the application by running npm start from the command line in the project root folder.


Adding Alerts / Toaster Notifications to Your Angular 2/4 App

To add alerts to your Angular 2/4 application you'll need to copy the following files from the example project:

  • app/_directives/alert.component.html - directive template that contains the html for displaying alerts.
  • app/_directives/alert.component.ts - alert directive that controls the adding & removing of alerts.
  • app/_models/alert.ts - alert model class that defines the properties of an alert, it also includes the alert type enum that defines the different types of alerts.
  • app/_services/alert.service.ts - alert service that is used by any application component to send alerts to the alert component.


Update AppModule to include AlertComponent and AlertServicie

To make the alert directive component and alert service available to your application you need to add them to the declarations and providers sections of your app.module.ts, here is the app module from the example app with the alert sections commented.

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent }  from './app.component';
import { routing }        from './app.routing';

// import alert service and component
import { AlertComponent } from './_directives/index';
import { AlertService } from './_services/index';

import { HomeComponent } from './home/index';

@NgModule({
    imports: [
        BrowserModule,
        routing
    ],
    declarations: [
        AppComponent,

        // include alert directive component in app module declarations
        AlertComponent,

        HomeComponent
    ],
    providers: [
        // include alert service in app module providers
        AlertService
    ],
    bootstrap: [AppComponent]
})

export class AppModule { }


Add the <alert></alert> tag to the app component template

Add the alert tag to your app.component.html file where you want alert messages to be displayed, here is the app compenent template from the example app, it places the alert tag directly above the router-outlet tag.

<!-- main app container -->
<div class="jumbotron">
    <div class="container">
        <div class="col-sm-8 col-sm-offset-2">
            <alert></alert>
            <router-outlet></router-outlet>
        </div>
    </div>
</div>


Displaying Alert / Toaster Notifications in Your Angular 2/4 App

Once you've added support for alerts / toaster notifications to your app by following the previous steps, you can trigger alert notifications from any component in your application by simply injecting the alert service and calling one of it's methods for displaying different types of alerts: success(), error(), info() and warn().

Here is the home component from the example app that contains methods that pass example notification messages to the alert service when each of the buttons is clicked. In a real world application alert notifications can be triggered by any type of event, for example an error from an http request or a success message after a user profile is saved.

import { Component } from '@angular/core';

import { AlertService } from '../_services/index';

@Component({
    moduleId: module.id,
    templateUrl: 'home.component.html'
})

export class HomeComponent {
    constructor(private alertService: AlertService) { }

    success(message: string) { 
        this.alertService.success(message);
    }

    error(message: string) {
        this.alertService.error(message);
    }

    info(message: string) {
        this.alertService.info(message);
    }

    warn(message: string) {
        this.alertService.warn(message);
    }

    clear() {
        this.alertService.clear();
    }
}


And here is the home component template containing the buttons that are bound to the above methods.

<div class="col-md-10 col-md-offset-1 text-center">
    <h1>Angular 2/4 Alerts</h1>
    <button class="btn btn-success" (click)="success('Success!!')">Success</button>
    <button class="btn btn-danger" (click)="error('Error :(')">Error</button>
    <button class="btn btn-info" (click)="info('Some info....')">Info</button>
    <button class="btn btn-warning" (click)="warn('Warning: ...')">Warn</button>
    <button class="btn btn-default" (click)="clear()">Clear</button>
</div>

 


 

Breakdown of the Angular 2/4 Alert / Toaster Notification Code

Below is a breakdown of the pieces of code used to implement the alert / toaster notification example in Angular 2/4, you don't need to know the details of how it all works to use the alerts in your project, it's only if you're interested in the nuts and bolts or if you want to modify the code or behaviour.


Angular 2/4 Alert Service

The alert service acts as the bridge between any component in an Angular 2/4 application and the alert component that actually displays the alert / toaster messages. It contains methods for sending and clearing alert messages, it also subscribes to the router 'NavigationStart' event to automatically clear alert messages on route change, unless the keepAfterRouteChange flag is set to true, in which case the alert messages survive a single route change and are cleared on the next route change.

The service uses the Observable and Subject classes to enable communication with other components, for more information on how this works see Angular 2/4 - Communicating Between Components with Observable & Subject.

import { Injectable } from '@angular/core';
import { Router, NavigationStart } from '@angular/router';
import { Observable } from 'rxjs';
import { Subject } from 'rxjs/Subject';

import { Alert, AlertType } from '../_models/alert';

@Injectable()
export class AlertService {
    private subject = new Subject<Alert>();
    private keepAfterRouteChange = false;

    constructor(private router: Router) {
        // clear alert messages on route change unless 'keepAfterRouteChange' flag is true
        router.events.subscribe(event => {
            if (event instanceof NavigationStart) {
                if (this.keepAfterRouteChange) {
                    // only keep for a single route change
                    this.keepAfterRouteChange = false;
                } else {
                    // clear alert messages
                    this.clear();
                }
            }
        });
    }

    getAlert(): Observable<any> {
        return this.subject.asObservable();
    }

    success(message: string, keepAfterRouteChange = false) {
        this.alert(AlertType.Success, message, keepAfterRouteChange);
    }

    error(message: string, keepAfterRouteChange = false) {
        this.alert(AlertType.Error, message, keepAfterRouteChange);
    }

    info(message: string, keepAfterRouteChange = false) {
        this.alert(AlertType.Info, message, keepAfterRouteChange);
    }

    warn(message: string, keepAfterRouteChange = false) {
        this.alert(AlertType.Warning, message, keepAfterRouteChange);
    }

    alert(type: AlertType, message: string, keepAfterRouteChange = false) {
        this.keepAfterRouteChange = keepAfterRouteChange;
        this.subject.next(<Alert>{ type: type, message: message });
    }

    clear() {
        // clear alerts
        this.subject.next();
    }
}


Angular 2/4 Alert Directive Component

The alert directive controls the adding & removing of alerts, it maintains an array of alerts that are displayed by the component template.

In the ngOnInit method the component subscribes to the observable returned from the alertService.getAlert() method, which enables the alert component to be notified whenever an alert message is sent to the alert service and add it to the alerts array for display. When an empty / undefined alert is received the alerts array is cleared.

The cssClass() method returns a corresponding bootstrap alert class for each of the alert types, if you're using something other than bootstrap you can change the css classes returned to suit your application.

import { Component, OnInit } from '@angular/core';

import { Alert, AlertType } from '../_models/index';
import { AlertService } from '../_services/index';

@Component({
    moduleId: module.id,
    selector: 'alert',
    templateUrl: 'alert.component.html'
})

export class AlertComponent {
    alerts: Alert[] = [];

    constructor(private alertService: AlertService) { }

    ngOnInit() {
        this.alertService.getAlert().subscribe((alert: Alert) => {
            if (!alert) {
                // clear alerts when an empty alert is received
                this.alerts = [];
                return;
            }

            // add alert to array
            this.alerts.push(alert);
        });
    }

    removeAlert(alert: Alert) {
        this.alerts = this.alerts.filter(x => x !== alert);
    }

    cssClass(alert: Alert) {
        if (!alert) {
            return;
        }

        // return css class based on alert type
        switch (alert.type) {
            case AlertType.Success:
                return 'alert alert-success';
            case AlertType.Error:
                return 'alert alert-danger';
            case AlertType.Info:
                return 'alert alert-info';
            case AlertType.Warning:
                return 'alert alert-warning';
        }
    }
}


Angular 2/4 Alert Directive Template

The alert directive template simply displays an alert message for each alert in the alerts array. Bootstrap is used for styling the alerts / toaster notifications, but you can change the html and css classes here to suit your application if you're not using bootstrap.

<div *ngFor="let alert of alerts" class="{{ cssClass(alert) }} alert-dismissable">
     {{alert.message}}
     <a class="close" (click)="removeAlert(alert)">&times;</a>
</div>


Angular 2/4 Alert Model and Alert Type enum

The alert model class defines the properties of each alert object, and the alert type enum defines the types of alerts allowed in the application.

export class Alert {
    type: AlertType;
    message: string;
}

export enum AlertType {
    Success,
    Error,
    Info,
    Warning
}

 

Recommended Books on Angular 2/4


Web Developer Sydney

Feel free to drop me a line if you're looking for an Angular 2/4 developer or web developer in Sydney Australia, I also provide remote contracting services for clients outside Sydney.


Sponsored by