1 import {Component, Input, OnInit, ViewChild, TemplateRef, EventEmitter} from '@angular/core';
2 import {Observable, Observer} from 'rxjs';
3 import {NgbModal, NgbModalRef, NgbModalOptions} from '@ng-bootstrap/ng-bootstrap';
6 * Dialog base class. Handles the ngbModal logic.
7 * Sub-classed component templates must have a #dialogContent selector
8 * at the root of the template (see ConfirmDialogComponent).
10 * Dialogs interact with the caller via Observable.
12 * dialog.open().subscribe(
13 * value => handleValue(value),
14 * error => handleError(error),
15 * () => console.debug('dialog closed')
18 * It is up to the dialog implementer to decide what values to
19 * pass to the caller via the dialog.respond(data) and/or
20 * dialog.close(data) methods.
22 * dialog.close(...) closes the modal window and completes the
23 * observable, unless an error was previously passed, in which
24 * case the observable is already complete.
26 * dialog.close() with no data closes the dialog without passing
27 * any values to the caller.
31 selector: 'eg-dialog',
32 template: '<ng-template></ng-template>'
34 export class DialogComponent implements OnInit {
36 // Track instances so we can refer to them later in closeAll()
37 // NOTE this could also be done by importing router and subscribing
38 // to route events here, but that would require all subclassed
39 // components to import and pass the router via the constructor.
41 static instances: {[ident: number]: any} = {};
43 // Assume all dialogs support a title attribute.
44 @Input() public dialogTitle: string;
46 // Pointer to the dialog content template.
47 @ViewChild('dialogContent', {static: false})
48 private dialogContent: TemplateRef<any>;
50 identifier: number = DialogComponent.counter++;
52 // Emitted after open() is called on the ngbModal.
53 // Note when overriding open(), this will not fire unless also
54 // called in the overridding method.
55 onOpen$ = new EventEmitter<any>();
57 // How we relay responses to the caller.
58 observer: Observer<any>;
60 // The modalRef allows direct control of the modal instance.
61 private modalRef: NgbModalRef = null;
63 constructor(private modalService: NgbModal) {}
65 // Close all active dialogs
67 Object.keys(DialogComponent.instances).forEach(id => {
68 if (DialogComponent.instances[id]) {
69 DialogComponent.instances[id].close();
70 delete DialogComponent.instances[id];
76 this.onOpen$ = new EventEmitter<any>();
79 open(options: NgbModalOptions = { backdrop: 'static' }): Observable<any> {
81 if (this.modalRef !== null) {
82 this.error('Dialog was replaced!');
86 // force backdrop to static if caller passed in any options
87 options.backdrop = 'static';
89 this.modalRef = this.modalService.open(this.dialogContent, options);
90 DialogComponent.instances[this.identifier] = this;
93 // Let the digest cycle complete
94 setTimeout(() => this.onOpen$.emit(true));
97 return new Observable(observer => {
98 this.observer = observer;
100 this.modalRef.result.then(
101 // Results are relayed to the caller via our observer.
102 // Our Observer is marked complete via this.close().
103 // Nothing to do here.
106 // Modal was dismissed via UI control which
107 // bypasses call to this.close()
108 dismissed => this.finalize()
113 // Send a response to the caller without closing the dialog.
114 respond(value: any) {
115 if (this.observer && value !== undefined) {
116 this.observer.next(value);
120 // Sends error event to the caller and closes the dialog.
121 // Once an error is sent, our observable is complete and
122 // cannot be used again to send any messages.
123 error(value: any, close?: boolean) {
125 console.error('Dialog produced error', value);
126 this.observer.error(value);
127 this.observer = null;
129 if (this.modalRef) { this.modalRef.close(); }
133 // Close the dialog, optionally with a value to relay to the caller.
134 // Calling close() with no value simply dismisses the dialog.
137 if (this.modalRef) { this.modalRef.close(); }
142 console.warn('Dialog.dismiss() is deprecated. Use close() instead');
146 // Clean up after closing the dialog.
148 if (this.observer) { // null if this.error() called
149 this.observer.complete();
150 this.observer = null;
152 this.modalRef = null;
153 delete DialogComponent.instances[this.identifier];