import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { Popup } from "./popup.component";
import { PopupService } from "./popup.service";
import { PopupA } from './popups/a.component';
import { PopupB } from './popups/b.component';
@NgModule({
imports: [
BrowserModule
],
providers: [PopupService],
declarations: [
AppComponent, Popup, PopupA, PopupB
],
entryComponents: [PopupA, PopupB],
bootstrap: [ AppComponent ]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
<!DOCTYPE html>
<html>
<head>
<title>Popup example</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="style.css">
<!-- Polyfills for older browsers -->
<script src="https://unpkg.com/core-js/client/shim.min.js"></script>
<script src="https://unpkg.com/zone.js@0.6.25?main=browser"></script>
<script src="https://unpkg.com/reflect-metadata@0.1.8"></script>
<script src="https://unpkg.com/systemjs@0.19.39/dist/system.src.js"></script>
<script src="https://cdn.rawgit.com/angular/angular.io/f2daab7/public/docs/_examples/_boilerplate/systemjs.config.web.js"></script>
</head>
<body app-root></body>
</html>
import { Component } from "@angular/core";
import { Popup } from "./popup.component";
import { PopupService } from './popup.service';
import { PopupA } from './popups/a.component';
import { PopupB } from './popups/b.component';
@Component({
selector: "[app-root]",
directives: [Popup],
templateUrl: "app/app.component.html"
})
export class AppComponent {
constructor(private popupService: PopupService) {}
openA() {
this.popupService.open(PopupA, [
{
provide: "id", useValue: "hello from a"
}
]);
}
openB() {
this.popupService.open(PopupB, [
{
provide: "id", useValue: "hello from b"
}
]);
}
}
<div cass="container">
<div class="row padding">
<popup-overflow></popup-overflow>
<button (click)="openA()" class="btn btn-primary btn-lg">Open popup A</button>
<button (click)="openB()" class="btn btn-default btn-lg">Open popup B</button>
</div>
</div>
.padding{
padding: 20px;
}
.loader {
background-color: #000000;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 9999;
position: absolute;
opacity: 0.4;
}
.spinner {
margin: 100px auto;
width: 50px;
height: 40px;
text-align: center;
font-size: 10px;
}
.spinner > div {
background-color: #333;
height: 100%;
width: 6px;
display: inline-block;
-webkit-animation: sk-stretchdelay 1.2s infinite ease-in-out;
animation: sk-stretchdelay 1.2s infinite ease-in-out;
}
.spinner .rect2 {
-webkit-animation-delay: -1.1s;
animation-delay: -1.1s;
}
.spinner .rect3 {
-webkit-animation-delay: -1.0s;
animation-delay: -1.0s;
}
.spinner .rect4 {
-webkit-animation-delay: -0.9s;
animation-delay: -0.9s;
}
.spinner .rect5 {
-webkit-animation-delay: -0.8s;
animation-delay: -0.8s;
}
@-webkit-keyframes sk-stretchdelay {
0%, 40%, 100% { -webkit-transform: scaleY(0.4) }
20% { -webkit-transform: scaleY(1.0) }
}
@keyframes sk-stretchdelay {
0%, 40%, 100% {
transform: scaleY(0.4);
-webkit-transform: scaleY(0.4);
} 20% {
transform: scaleY(1.0);
-webkit-transform: scaleY(1.0);
}
}
.modal.in {
display: block;
}
import {
Component, OnDestroy, OnInit, ReflectiveInjector, Injector, ComponentFactoryResolver
} from '@angular/core';
import {PopupService, PopupEvent} from './popup.service';
import {ViewContainerRef} from '@angular/core';
import {Subscription} from 'rxjs/Subscription';
import { PopupA } from './popups/a.component';
import { PopupB } from './popups/b.component';
@Component({
selector: 'popup-overflow',
templateUrl: 'app/popup.component.html'
})
export class Popup implements OnDestroy, OnInit {
loading: false;
subscribers: Array<Subscription> = [];
constructor(private popupService: PopupService,
private injector: Injector,
private componentFactoryResolver: ComponentFactoryResolver,
private viewContainerRef: ViewContainerRef) {
}
ngOnInit() {
this.subscribers.push(
this.popupService.subscribe((data) => {
if (!!data && data.operation === PopupEvent.OPEN) {
this.open(data);
} else if (data &&
(
data.operation === PopupEvent.CLOSE ||
data.operation === PopupEvent.DESTROY
)
) {
this.close();
}
})
);
}
ngOnDestroy() {
if (this.subscribers) {
this.subscribers.forEach(item => item.unsubscribe());
this.subscribers = null;
}
}
private open(data) {
this.loading = true;
let providers = data.providers || [];
let injector = ReflectiveInjector.resolveAndCreate(providers, this.injector);
let factory = this.componentFactoryResolver.resolveComponentFactory(data.component);
setTimeout(() => {
this.loading = false;
this.viewContainerRef.createComponent(factory, 0, injector);
}, 1000);
}
private close() {
this.viewContainerRef.detach(0);
}
}
import {Injectable, EventEmitter} from '@angular/core';
export enum PopupEvent {
OPEN, DESTROY, CLOSE
}
@Injectable()
export class PopupService {
private currentPopupView: EventEmitter<any> = new EventEmitter<any>();
private _isOpened: boolean = false;
isOpened(): boolean {
return this._isOpened;
}
open(component: any, providers?: Array<any>): void {
if (this._isOpened) {
this.destroy();
}
this.fireEvent(PopupEvent.OPEN, true, {
component: component,
providers: providers
});
}
destroy() {
this.fireEvent(PopupEvent.DESTROY, false);
}
close(): void {
this.fireEvent(PopupEvent.CLOSE, false);
}
subscribe(generatorOrNext?: any, error?: any, complete?: any) {
this.currentPopupView.subscribe(generatorOrNext, error, complete);
}
private fireEvent(name: PopupEvent, status: boolean, data?: any) {
let _current = this._isOpened;
this._isOpened = status;
let event = {
operation: name,
status: {
current: this._isOpened,
old: _current
},
};
if (typeof data === "object" && data != null) {
Object.assign(event, data);
}
this.currentPopupView.emit(event);
}
}
<div [ngClass]="{'loader': loading}" >
<div *ngIf="loading" class="spinner">
<div class="rect1"></div>
<div class="rect2"></div>
<div class="rect3"></div>
<div class="rect4"></div>
<div class="rect5"></div>
</div>
</div>
import {Component, OnInit, Inject} from '@angular/core';
import {PopupService} from '../popup.service';
@Component({
selector: 'popup-a-view',
templateUrl: "app/popups/a.component.html"
})
export class PopupA {
id: string;
constructor(
private popupService: PopupService,
@Inject("id") id: string
) {
this.id = id;
}
close() {
this.popupService.close();
}
}
import {Component, OnInit, Inject} from '@angular/core';
import {PopupService} from '../popup.service';
@Component({
selector: 'popup-b-view',
templateUrl: "app/popups/b.component.html"
})
export class PopupB {
id: string;
constructor(
private popupService: PopupService,
@Inject("id") id: string
) {
this.id = id;
}
close() {
this.popupService.close();
}
}
<div class="modal fade in">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Modal title A</h4>
</div>
<div class="modal-body">
This is popup a: {{ id }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" (click)="close()">Close</button>
</div>
</div>
</div>
</div>
<div class="modal fade in">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Modal title B</h4>
</div>
<div class="modal-body">
This is popup b: {{ id }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" (click)="close()">Close</button>
</div>
</div>
</div>
</div>