This repository has been archived by the owner on Mar 29, 2024. It is now read-only.
/
dialog.service.ts
135 lines (118 loc) · 4.18 KB
/
dialog.service.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import { Overlay, OverlayConfig, OverlayPositionBuilder, PositionStrategy } from '@angular/cdk/overlay';
import { ComponentPortal, ComponentType, TemplatePortal } from '@angular/cdk/portal';
import { ComponentRef, EmbeddedViewRef, Injectable, Injector } from '@angular/core';
import { filter, take, takeUntil } from 'rxjs/operators';
import { ConfirmDailogComponent, ConfirmDialogConfig, CONFIRM_DIALOG_CONFIG } from './confirm.dialog';
import { DialogContainer } from './dialog.container';
import { DialogModule } from './dialog.module';
import { DialogRef, DIALOG_REF } from './dialog.ref';
export interface BaseDialogConfig {
/** whether or not the dialog should close on outside-clicks and ESC */
autoclose?: boolean;
/** whether or not a backdrop should be visible */
backdrop?: boolean | 'light';
/** whether or not the dialog should be dragable */
dragable?: boolean;
/**
* optional position strategy for the overlay. if omitted, the
* overlay will be centered on the screen
*/
positionStrategy?: PositionStrategy;
}
export interface ComponentPortalConfig {
injector?: Injector;
}
@Injectable({ providedIn: DialogModule })
export class DialogService {
constructor(
private injector: Injector,
private overlay: Overlay,
) { }
position(): OverlayPositionBuilder {
return this.overlay.position();
}
create<T>(template: TemplatePortal<T>, opts?: BaseDialogConfig): DialogRef<EmbeddedViewRef<T>>;
create<T>(target: ComponentType<T>, opts?: BaseDialogConfig & ComponentPortalConfig): DialogRef<ComponentRef<T>>;
create<T>(target: ComponentType<T> | TemplatePortal<T>, opts: BaseDialogConfig & ComponentPortalConfig = {}): DialogRef<any> {
let position: PositionStrategy = opts?.positionStrategy || this.overlay
.position()
.global()
.centerVertically()
.centerHorizontally();
let hasBackdrop = true;
let backdropClass = 'dialog-screen-backdrop';
if (opts.backdrop !== undefined) {
if (opts.backdrop === false) {
hasBackdrop = false;
} else if (opts.backdrop === 'light') {
backdropClass = 'dialog-screen-backdrop-light';
}
}
const cfg = new OverlayConfig({
scrollStrategy: this.overlay.scrollStrategies.noop(),
positionStrategy: position,
hasBackdrop: hasBackdrop,
backdropClass: backdropClass,
});
const overlayref = this.overlay.create(cfg);
// create our dialog container and attach it to the
// overlay.
const containerPortal = new ComponentPortal(
DialogContainer,
undefined,
this.injector,
)
const containerRef = containerPortal.attach(overlayref);
if (!!opts.dragable) {
containerRef.instance.dragable = true;
}
// create the dialog ref
const dialogRef = new DialogRef<T>(overlayref, containerRef.instance);
// prepare the content portal and attach it to the container
let result: any;
if (target instanceof TemplatePortal) {
result = containerRef.instance.attachTemplatePortal(target)
} else {
const contentPortal = new ComponentPortal(target, null, Injector.create({
providers: [
{
provide: DIALOG_REF,
useValue: dialogRef,
}
],
parent: opts?.injector || this.injector,
}));
result = containerRef.instance.attachComponentPortal(contentPortal);
}
// update the container position now that we have some content.
overlayref.updatePosition();
if (!!opts?.autoclose) {
overlayref.outsidePointerEvents()
.pipe(take(1))
.subscribe(() => dialogRef.close());
overlayref.keydownEvents()
.pipe(
takeUntil(overlayref.detachments()),
filter(event => event.key === 'Escape')
)
.subscribe(() => {
dialogRef.close();
})
}
return dialogRef;
}
confirm(opts: ConfirmDialogConfig): DialogRef<ConfirmDailogComponent, string> {
return this.create(ConfirmDailogComponent, {
autoclose: opts.canCancel,
injector: Injector.create({
providers: [
{
provide: CONFIRM_DIALOG_CONFIG,
useValue: opts,
},
],
parent: this.injector,
})
})
}
}