<!DOCTYPE html>
<html>
<head>
<base href="." />
<script type="text/javascript" charset="utf-8">
window.AngularVersionForThisPlunker = 'latest'
</script>
<title>angular playground</title>
<link href="https://ng-bootstrap.github.io/css/vendorStyles.6e6350aa116791800d06.css" rel="stylesheet">
<link rel="stylesheet" href="style.css" />
<script src="https://unpkg.com/core-js@2.4.1/client/shim.min.js"></script>
<script src="https://unpkg.com/zone.js/dist/zone.js"></script>
<script src="https://unpkg.com/zone.js/dist/long-stack-trace-zone.js"></script>
<script src="https://unpkg.com/reflect-metadata@0.1.3/Reflect.js"></script>
<script src="https://unpkg.com/systemjs@0.19.31/dist/system.js"></script>
<script src="config.js"></script>
<script>
System.import('app')
.catch(console.error.bind(console));
</script>
</head>
<body>
<my-app>
loading...
</my-app>
</body>
</html>
/* Styles go here */
### Angular Starter Plunker - Typescript
var angularVersion;
if(window.AngularVersionForThisPlunker === 'latest'){
angularVersion = ''; //picks up latest
}
else {
angularVersion = '@' + window.AngularVersionForThisPlunker;
}
System.config({
//use typescript for compilation
transpiler: 'typescript',
//typescript compiler options
typescriptOptions: {
emitDecoratorMetadata: true
},
paths: {
'npm:': 'https://unpkg.com/'
},
//map tells the System loader where to look for things
map: {
'app': './src',
'@angular/core': 'npm:@angular/core'+ angularVersion + '/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common' + angularVersion + '/bundles/common.umd.js',
'@angular/common/http': 'npm:@angular/common' + angularVersion + '/bundles/common-http.umd.js',
'@angular/compiler': 'npm:@angular/compiler' + angularVersion + '/bundles/compiler.umd.js',
'@angular/platform-browser': 'npm:@angular/platform-browser' + angularVersion + '/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic' + angularVersion + '/bundles/platform-browser-dynamic.umd.js',
'@angular/http': 'npm:@angular/http' + angularVersion + '/bundles/http.umd.js',
'@angular/router': 'npm:@angular/router' + angularVersion +'/bundles/router.umd.js',
'@angular/forms': 'npm:@angular/forms' + angularVersion + '/bundles/forms.umd.js',
'@angular/animations': 'npm:@angular/animations' + angularVersion + '/bundles/animations.umd.js',
'@angular/platform-browser/animations': 'npm:@angular/platform-browser' + angularVersion + '/bundles/platform-browser-animations.umd.js',
'@angular/animations/browser': 'npm:@angular/animations' + angularVersion + '/bundles/animations-browser.umd.js',
'@angular/core/testing': 'npm:@angular/core' + angularVersion + '/bundles/core-testing.umd.js',
'@angular/common/testing': 'npm:@angular/common' + angularVersion + '/bundles/common-testing.umd.js',
'@angular/common/http/testing': 'npm:@angular/common' + angularVersion + '/bundles/common-http-testing.umd.js',
'@angular/compiler/testing': 'npm:@angular/compiler' + angularVersion + '/bundles/compiler-testing.umd.js',
'@angular/platform-browser/testing': 'npm:@angular/platform-browser' + angularVersion + '/bundles/platform-browser-testing.umd.js',
'@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic' + angularVersion + '/bundles/platform-browser-dynamic-testing.umd.js',
'@angular/http/testing': 'npm:@angular/http' + angularVersion + '/bundles/http-testing.umd.js',
'@angular/router/testing': 'npm:@angular/router' + angularVersion + '/bundles/router-testing.umd.js',
'tslib': 'npm:tslib@1.6.1',
'rxjs': 'npm:rxjs',
'typescript': 'npm:typescript@2.2.1/lib/typescript.js'
},
//packages defines our app package
packages: {
app: {
main: './main.ts',
defaultExtension: 'ts'
},
rxjs: {
defaultExtension: 'js'
}
}
});
//main entry point
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppModule} from './app';
platformBrowserDynamic().bootstrapModule(AppModule)
//our root app component
import {Component, NgModule, VERSION} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import {NgbModalModule, NgbModal, ModalDismissReasons} from './modal/modal.module'
@Component({
selector: 'my-app',
template: `
<div class="container">
<h2>Modal example</h2>
<ng-template #content let-c="close" let-d="dismiss">
<div class="modal-header">
<h4 class="modal-title">Modal title</h4>
<button type="button" class="close" aria-label="Close" (click)="d('Cross click')">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>One fine body…</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-dark" (click)="c('Close click')">Close</button>
</div>
</ng-template>
<button class="btn btn-lg btn-outline-primary" (click)="open(content)">Launch demo modal</button>
<hr>
</div>
`,
})
export class App {
closeResult: string;
constructor(private modalService: NgbModal) {}
open(content) {
this.modalService.open(content).result.then((result) => {
this.closeResult = `Closed with: ${result}`;
}, (reason) => {
this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
});
}
private getDismissReason(reason: any): string {
if (reason === ModalDismissReasons.ESC) {
return 'by pressing ESC';
} else if (reason === ModalDismissReasons.BACKDROP_CLICK) {
return 'by clicking on a backdrop';
} else {
return `with: ${reason}`;
}
}
}
@NgModule({
imports: [ BrowserModule, NgbModalModule.forRoot() ],
declarations: [ App ],
bootstrap: [ App ]
})
export class AppModule {}
import {Injectable, Injector, ComponentFactoryResolver} from '@angular/core';
import {NgbModalStack} from './modal-stack';
import {NgbModalRef} from './modal-ref';
/**
* Represent options available when opening new modal windows.
*/
export interface NgbModalOptions {
/**
* Whether a backdrop element should be created for a given modal (true by default).
* Alternatively, specify 'static' for a backdrop which doesn't close the modal on click.
*/
backdrop?: boolean | 'static';
/**
* Function called when a modal will be dismissed.
* If this function returns false, the modal is not dismissed.
*/
beforeDismiss?: () => boolean;
/**
* An element to which to attach newly opened modal windows.
*/
container?: string;
/**
* Injector to use for modal content.
*/
injector?: Injector;
/**
* Whether to close the modal when escape key is pressed (true by default).
*/
keyboard?: boolean;
/**
* Size of a new modal window.
*/
size?: 'sm' | 'lg';
/**
* Custom class to append to the modal window
*/
windowClass?: string;
}
/**
* A service to open modal windows. Creating a modal is straightforward: create a template and pass it as an argument to
* the "open" method!
*/
@Injectable()
export class NgbModal {
constructor(
private _moduleCFR: ComponentFactoryResolver, private _injector: Injector, private _modalStack: NgbModalStack) {}
/**
* Opens a new modal window with the specified content and using supplied options. Content can be provided
* as a TemplateRef or a component type. If you pass a component type as content than instances of those
* components can be injected with an instance of the NgbActiveModal class. You can use methods on the
* NgbActiveModal class to close / dismiss modals from "inside" of a component.
*/
open(content: any, options: NgbModalOptions = {}): NgbModalRef {
return this._modalStack.open(this._moduleCFR, this._injector, content, options);
}
}
import {NgModule, ModuleWithProviders} from '@angular/core';
import {NgbModalBackdrop} from './modal-backdrop';
import {NgbModalWindow} from './modal-window';
import {NgbModalStack} from './modal-stack';
import {NgbModal} from './modal';
export {NgbModal, NgbModalOptions} from './modal';
export {NgbModalRef, NgbActiveModal} from './modal-ref';
export {ModalDismissReasons} from './modal-dismiss-reasons';
@NgModule({
declarations: [NgbModalBackdrop, NgbModalWindow],
entryComponents: [NgbModalBackdrop, NgbModalWindow],
providers: [NgbModal]
})
export class NgbModalModule {
static forRoot(): ModuleWithProviders { return {ngModule: NgbModalModule, providers: [NgbModal, NgbModalStack]}; }
}
import {Component} from '@angular/core';
@Component({selector: 'ngb-modal-backdrop', template: '', host: {'class': 'modal-backdrop fade show'}})
export class NgbModalBackdrop {
}
export class ModalDismissReasons {
BACKDROP_CLICK,
ESC
}
import {ComponentRef} from '@angular/core';
import {NgbModalBackdrop} from './modal-backdrop';
import {NgbModalWindow} from './modal-window';
import {ContentRef} from '../util/popup';
/**
* A reference to an active (currently opened) modal. Instances of this class
* can be injected into components passed as modal content.
*/
export class NgbActiveModal {
/**
* Can be used to close a modal, passing an optional result.
*/
close(result?: any): void {}
/**
* Can be used to dismiss a modal, passing an optional reason.
*/
dismiss(reason?: any): void {}
}
/**
* A reference to a newly opened modal.
*/
export class NgbModalRef {
private _resolve: (result?: any) => void;
private _reject: (reason?: any) => void;
/**
* The instance of component used as modal's content.
* Undefined when a TemplateRef is used as modal's content.
*/
get componentInstance(): any {
if (this._contentRef.componentRef) {
return this._contentRef.componentRef.instance;
}
}
// only needed to keep TS1.8 compatibility
set componentInstance(instance: any) {}
/**
* A promise that is resolved when a modal is closed and rejected when a modal is dismissed.
*/
result: Promise<any>;
constructor(
private _windowCmptRef: ComponentRef<NgbModalWindow>, private _contentRef: ContentRef,
private _backdropCmptRef?: ComponentRef<NgbModalBackdrop>, private _beforeDismiss?: Function) {
_windowCmptRef.instance.dismissEvent.subscribe((reason: any) => { this.dismiss(reason); });
this.result = new Promise((resolve, reject) => {
this._resolve = resolve;
this._reject = reject;
});
this.result.then(null, () => {});
}
/**
* Can be used to close a modal, passing an optional result.
*/
close(result?: any): void {
if (this._windowCmptRef) {
this._resolve(result);
this._removeModalElements();
}
}
/**
* Can be used to dismiss a modal, passing an optional reason.
*/
dismiss(reason?: any): void {
if (this._windowCmptRef) {
if (!this._beforeDismiss || this._beforeDismiss() !== false) {
this._reject(reason);
this._removeModalElements();
}
}
}
private _removeModalElements() {
const windowNativeEl = this._windowCmptRef.location.nativeElement;
windowNativeEl.parentNode.removeChild(windowNativeEl);
this._windowCmptRef.destroy();
if (this._backdropCmptRef) {
const backdropNativeEl = this._backdropCmptRef.location.nativeElement;
backdropNativeEl.parentNode.removeChild(backdropNativeEl);
this._backdropCmptRef.destroy();
}
if (this._contentRef && this._contentRef.viewRef) {
this._contentRef.viewRef.destroy();
}
this._windowCmptRef = null;
this._backdropCmptRef = null;
this._contentRef = null;
}
}
import {
ApplicationRef,
Injectable,
Injector,
ReflectiveInjector,
ComponentFactory,
ComponentFactoryResolver,
ComponentRef,
TemplateRef
} from '@angular/core';
import {ContentRef} from '../util/popup';
import {isDefined, isString} from '../util/util';
import {NgbModalBackdrop} from './modal-backdrop';
import {NgbModalWindow} from './modal-window';
import {NgbActiveModal, NgbModalRef} from './modal-ref';
@Injectable()
export class NgbModalStack {
private _backdropFactory: ComponentFactory<NgbModalBackdrop>;
private _windowFactory: ComponentFactory<NgbModalWindow>;
constructor(
private _applicationRef: ApplicationRef, private _injector: Injector,
private _componentFactoryResolver: ComponentFactoryResolver) {
this._backdropFactory = _componentFactoryResolver.resolveComponentFactory(NgbModalBackdrop);
this._windowFactory = _componentFactoryResolver.resolveComponentFactory(NgbModalWindow);
}
open(moduleCFR: ComponentFactoryResolver, contentInjector: Injector, content: any, options): NgbModalRef {
const containerSelector = options.container || 'body';
const containerEl = document.querySelector(containerSelector);
if (!containerEl) {
throw new Error(`The specified modal container "${containerSelector}" was not found in the DOM.`);
}
const activeModal = new NgbActiveModal();
const contentRef = this._getContentRef(moduleCFR, options.injector || contentInjector, content, activeModal);
let windowCmptRef: ComponentRef<NgbModalWindow>;
let backdropCmptRef: ComponentRef<NgbModalBackdrop>;
let ngbModalRef: NgbModalRef;
if (options.backdrop !== false) {
backdropCmptRef = this._backdropFactory.create(this._injector);
this._applicationRef.attachView(backdropCmptRef.hostView);
containerEl.appendChild(backdropCmptRef.location.nativeElement);
}
windowCmptRef = this._windowFactory.create(this._injector, contentRef.nodes);
this._applicationRef.attachView(windowCmptRef.hostView);
containerEl.appendChild(windowCmptRef.location.nativeElement);
ngbModalRef = new NgbModalRef(windowCmptRef, contentRef, backdropCmptRef, options.beforeDismiss);
activeModal.close = (result: any) => { ngbModalRef.close(result); };
activeModal.dismiss = (reason: any) => { ngbModalRef.dismiss(reason); };
this._applyWindowOptions(windowCmptRef.instance, options);
return ngbModalRef;
}
private _applyWindowOptions(windowInstance: NgbModalWindow, options: Object): void {
['backdrop', 'keyboard', 'size', 'windowClass'].forEach((optionName: string) => {
if (isDefined(options[optionName])) {
windowInstance[optionName] = options[optionName];
}
});
}
private _getContentRef(
moduleCFR: ComponentFactoryResolver, contentInjector: Injector, content: any,
context: NgbActiveModal): ContentRef {
if (!content) {
return new ContentRef([]);
} else if (content instanceof TemplateRef) {
const viewRef = content.createEmbeddedView(context);
this._applicationRef.attachView(viewRef);
return new ContentRef([viewRef.rootNodes], viewRef);
} else if (isString(content)) {
return new ContentRef([[document.createTextNode(`${content}`)]]);
} else {
const contentCmptFactory = moduleCFR.resolveComponentFactory(content);
const modalContentInjector =
ReflectiveInjector.resolveAndCreate([{provide: NgbActiveModal, useValue: context}], contentInjector);
const componentRef = contentCmptFactory.create(modalContentInjector);
this._applicationRef.attachView(componentRef.hostView);
return new ContentRef([[componentRef.location.nativeElement]], componentRef.hostView, componentRef);
}
}
}
import {
Component,
Output,
EventEmitter,
Input,
ElementRef,
Renderer2,
OnInit,
AfterViewInit,
OnDestroy
} from '@angular/core';
import {ModalDismissReasons} from './modal-dismiss-reasons';
@Component({
selector: 'ngb-modal-window',
host: {
'[class]': '"modal fade show" + (windowClass ? " " + windowClass : "")',
'role': 'dialog',
'tabindex': '-1',
'style': 'display: block;',
'(keyup.esc)': 'escKey($event)',
'(click)': 'backdropClick($event)'
},
template: `
<div [class]="'modal-dialog' + (size ? ' modal-' + size : '')" role="document">
<div class="modal-content"><ng-content></ng-content></div>
</div>
`
})
export class NgbModalWindow implements OnInit,
AfterViewInit, OnDestroy {
private _elWithFocus: Element; // element that is focused prior to modal opening
@Input() backdrop: boolean | string = true;
@Input() keyboard = true;
@Input() size: string;
@Input() windowClass: string;
@Output('dismiss') dismissEvent = new EventEmitter();
constructor(private _elRef: ElementRef, private _renderer: Renderer2) {}
backdropClick($event): void {
if (this.backdrop === true && this._elRef.nativeElement === $event.target) {
this.dismiss(ModalDismissReasons.BACKDROP_CLICK);
}
}
escKey($event): void {
if (this.keyboard && !$event.defaultPrevented) {
this.dismiss(ModalDismissReasons.ESC);
}
}
dismiss(reason): void { this.dismissEvent.emit(reason); }
ngOnInit() {
this._elWithFocus = document.activeElement;
this._renderer.addClass(document.body, 'modal-open');
}
ngAfterViewInit() {
if (!this._elRef.nativeElement.contains(document.activeElement)) {
this._elRef.nativeElement['focus'].apply(this._elRef.nativeElement, []);
}
}
ngOnDestroy() {
const body = document.body;
const elWithFocus = this._elWithFocus;
let elementToFocus;
if (elWithFocus && elWithFocus['focus'] && body.contains(elWithFocus)) {
elementToFocus = elWithFocus;
} else {
elementToFocus = body;
}
elementToFocus['focus'].apply(elementToFocus, []);
this._elWithFocus = null;
this._renderer.removeClass(body, 'modal-open');
}
}
import {
Injector,
TemplateRef,
ViewRef,
ViewContainerRef,
Renderer2,
ComponentRef,
ComponentFactory,
ComponentFactoryResolver
} from '@angular/core';
export class ContentRef {
constructor(public nodes: any[], public viewRef?: ViewRef, public componentRef?: ComponentRef<any>) {}
}
export class PopupService<T> {
private _windowFactory: ComponentFactory<T>;
private _windowRef: ComponentRef<T>;
private _contentRef: ContentRef;
constructor(
type: any, private _injector: Injector, private _viewContainerRef: ViewContainerRef, private _renderer: Renderer2,
componentFactoryResolver: ComponentFactoryResolver) {
this._windowFactory = componentFactoryResolver.resolveComponentFactory<T>(type);
}
open(content?: string | TemplateRef<any>, context?: any): ComponentRef<T> {
if (!this._windowRef) {
this._contentRef = this._getContentRef(content, context);
this._windowRef =
this._viewContainerRef.createComponent(this._windowFactory, 0, this._injector, this._contentRef.nodes);
}
return this._windowRef;
}
close() {
if (this._windowRef) {
this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._windowRef.hostView));
this._windowRef = null;
if (this._contentRef.viewRef) {
this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._contentRef.viewRef));
this._contentRef = null;
}
}
}
private _getContentRef(content: string | TemplateRef<any>, context?: any): ContentRef {
if (!content) {
return new ContentRef([]);
} else if (content instanceof TemplateRef) {
const viewRef = this._viewContainerRef.createEmbeddedView(<TemplateRef<T>>content, context);
return new ContentRef([viewRef.rootNodes], viewRef);
} else {
return new ContentRef([[this._renderer.createText(`${content}`)]]);
}
}
}
export function toInteger(value: any): number {
return parseInt(`${value}`, 10);
}
export function toString(value: any): string {
return (value !== undefined && value !== null) ? `${value}` : '';
}
export function getValueInRange(value: number, max: number, min = 0): number {
return Math.max(Math.min(value, max), min);
}
export function isString(value: any): value is string {
return typeof value === 'string';
}
export function isNumber(value: any): value is number {
return !isNaN(toInteger(value));
}
export function isInteger(value: any): value is number {
return typeof value === 'number' && isFinite(value) && Math.floor(value) === value;
}
export function isDefined(value: any): boolean {
return value !== undefined && value !== null;
}
export function padNumber(value: number) {
if (isNumber(value)) {
return `0${value}`.slice(-2);
} else {
return '';
}
}
export function regExpEscape(text) {
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
}