Skip to content

Instantly share code, notes, and snippets.

@uxder
Last active February 8, 2017 01:52
Show Gist options
  • Save uxder/2eb349dde3308096818bc24beb4714fa to your computer and use it in GitHub Desktop.
Save uxder/2eb349dde3308096818bc24beb4714fa to your computer and use it in GitHub Desktop.
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
export interface AlertConfig {
description?: string;
okButtonLabel?: string;
cancelButtonLabel?: string;
okCallback?: Function;
displayLoading?: boolean;
displayCloseButton?: boolean;
cssClass?: string;
}
/**
* Alert service is basically a modal type of UI component that allows you to
* notify user of an action.
*
* At the bottom of your page, add the alert component.
*
* <alert-component></alert-component>
*
* The alert component listens to the alert-service which emits a stream of
* states for the alert component.
*
* In your component or application, use the alert-service.
*
* All the configuration options for the alert component are essentially optional.
*
* Basic Alert:
*
* this.alertService.open({
* description: 'Are you sure you want to do this?',
* okButtonLabel: 'Yes',
* cancelButtonLabel: 'No',
* okCallback: ()=> {
* console.log('user clicked the ok button');
* },
* displayCloseButton: true,
* cssClass: 'text--centered'
* })
*
* The cssClass option allows you to add additional css for that model.
*
* You can also combine the alert to sequentially do work.
*
*
* this.alertService.open({
* description: 'Are you sure?',
* okButtonLabel: 'Yes',
* cancelButtonLabel: 'No',
* okCallback: ()=> {
*
* // Executed when the user clicks okay.
* // We now show an alert with ONLY the loading icon. Nothing else.
* // Note that the user can't cancel this action or get out of it until
* // you call the close on the alert service.
* this.alertService.open({
* displayLoading: true
* })
*
* // Now do something else that is async. Maybe an AJAX fetch call.
* myHttpService()
* .then(()=> {
* // Processing is done so dismiss the alert.
* this.alertService.close();
* })
* .catch(()=> {
* this.alertService.close();
* })
* }
* })
*
*
*
*
*/
@Injectable()
export class AlertService {
/**
* A stream that contains the current alert information.
* When this stream is updated to a null value, the user has dismissed
* the alert so the alert-component will disappear.
*/
private alertStream$: BehaviorSubject<AlertConfig>;
constructor() {
// Initialized the alert stream
this.alertStream$ = new BehaviorSubject(null);
}
/**
* Opens the alert component subscribed to this service by updating the
* alertStream.
*/
public open(config:AlertConfig) {
this.alertStream$.next(config);
}
/**
* Closes the alert component subscribed to this service by updating the
* alertStream to a null value.
*/
public close() {
this.alertStream$.next(null);
}
/**
* Returns the alertStream.
*/
public getStream():BehaviorSubject<AlertConfig> {
return this.alertStream$;
}
}
<div class="alert-component {{alertContents?.cssClass}}"
[ngClass]="
{ 'alert-component--active': alertContents }
">
<div class="alert-component__contents" *ngIf="alertContents">
<span class="alert-component__cancel"
*ngIf="alertContents.displayCloseButton"
(click)="close()">
<i class="material-icons">cancel</i>
</span>
<p *ngIf="alertContents.description">{{alertContents.description}}</p>
<p *ngIf="alertContents.displayLoading" class="text--centered">
<img src="./img/loading.gif">
</p>
<div class="push--top-sm text--centered">
<button *ngIf="alertContents.okButtonLabel" class="button button--small"
(click)="okay()"
>
{{alertContents.okButtonLabel}}
</button>
<button class="button button--small button--secondary"
(click)="close()"
*ngIf="alertContents.cancelButtonLabel">
{{alertContents.cancelButtonLabel}}
</button>
</div>
</div>
</div>
mport {Component, OnInit, Input, Output, ElementRef, HostBinding, EventEmitter} from "@angular/core";
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import {AlertService, AlertConfig} from './alert-service';
/**
* A simple componet to a loading process indicator.
*/
@Component({
selector: 'alert-component',
template: require('./alert.html')
})
export class AlertComponent {
private alertContents: AlertConfig;
private alertSubscription$: any;
constructor(
private alertService: AlertService
) {
this.alertSubscription$ = this.alertService.getStream().subscribe((value)=> {
this.alertContents = value;
})
}
/**
* Handles okay button click.
*/
private okay() {
// Copy over the callback to be called.
var callback = this.alertContents.okCallback;
this.close();
// Note we call the callback after closing to allow sequential alerts.
callback && callback();
}
/**
* Handles request to close.
*/
private close() {
this.alertService.close();
}
ngOnDestroy() {
this.alertSubscription$.unsubscribe();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment