/
modal.service.ts
100 lines (94 loc) · 3.13 KB
/
modal.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
import { Injectable } from '@angular/core';
import { Type } from '@vendure/common/lib/shared-types';
import { from, Observable } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
import { ModalDialogComponent } from '../../shared/components/modal-dialog/modal-dialog.component';
import { SimpleDialogComponent } from '../../shared/components/simple-dialog/simple-dialog.component';
import { OverlayHostService } from '../overlay-host/overlay-host.service';
import { Dialog, DialogConfig, ModalOptions } from './modal.types';
/**
* @description
* This service is responsible for instantiating a ModalDialog component and
* embedding the specified component within.
*
* @docsCategory services
* @docsPage ModalService
* @docsWeight 0
*/
@Injectable({
providedIn: 'root',
})
export class ModalService {
constructor(private overlayHostService: OverlayHostService) {}
/**
* @description
* Create a modal from a component. The component must implement the {@link Dialog} interface.
* Additionally, the component should include templates for the title and the buttons to be
* displayed in the modal dialog. See example:
*
* @example
* ```ts
* class MyDialog implements Dialog {
* resolveWith: (result?: any) => void;
*
* okay() {
* doSomeWork().subscribe(result => {
* this.resolveWith(result);
* })
* }
*
* cancel() {
* this.resolveWith(false);
* }
* }
* ```
*
* @example
* ```html
* <ng-template vdrDialogTitle>Title of the modal</ng-template>
*
* <p>
* My Content
* </p>
*
* <ng-template vdrDialogButtons>
* <button type="button"
* class="btn"
* (click)="cancel()">Cancel</button>
* <button type="button"
* class="btn btn-primary"
* (click)="okay()">Okay</button>
* </ng-template>
* ```
*/
fromComponent<T extends Dialog<any>, R>(
component: Type<T> & Type<Dialog<R>>,
options?: ModalOptions<T>,
): Observable<R | undefined> {
return from(this.overlayHostService.getHostView()).pipe(
mergeMap(hostView => {
const modalComponentRef = hostView.createComponent(ModalDialogComponent);
const modalInstance: ModalDialogComponent<any> = modalComponentRef.instance;
modalInstance.childComponentType = component;
modalInstance.options = options;
return new Observable<R>(subscriber => {
modalInstance.closeModal = (result: R) => {
modalComponentRef.destroy();
subscriber.next(result);
subscriber.complete();
};
});
}),
);
}
/**
* @description
* Displays a modal dialog with the provided title, body and buttons.
*/
dialog<T>(config: DialogConfig<T>): Observable<T | undefined> {
return this.fromComponent(SimpleDialogComponent, {
locals: config,
size: config.size,
});
}
}