summaryrefslogtreecommitdiffstats
path: root/sdc-workflow-designer-ui/src/app/paletx/plx-modal/modal-stack.ts
blob: 37f5b171e30dfb72c4e0412460e6379217fccd48 (plain)
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
import {
    ApplicationRef,
    Injectable,
    Injector,
    ReflectiveInjector,
    ComponentFactory,
    ComponentFactoryResolver,
    ComponentRef,
    TemplateRef
} from '@angular/core';

import {ContentRef} from '../util/popup';
import {isDefined, isString} from '../util/util';

import {PlxModalBackdrop} from './modal-backdrop';
import {PlxModalWindow} from './modal-window';
import {PlxActiveModal, PlxModalRef} from './modal-ref';

@Injectable()
export class PlxModalStack {
    private _backdropFactory: ComponentFactory<PlxModalBackdrop>;
    private _windowFactory: ComponentFactory<PlxModalWindow>;

    constructor(private _applicationRef: ApplicationRef, private _injector: Injector,
                private _componentFactoryResolver: ComponentFactoryResolver) {
        this._backdropFactory = _componentFactoryResolver.resolveComponentFactory(PlxModalBackdrop);
        this._windowFactory = _componentFactoryResolver.resolveComponentFactory(PlxModalWindow);
    }

    public open(moduleCFR: ComponentFactoryResolver, contentInjector: Injector, content: any, options): PlxModalRef {
        const containerSelector = options.container || 'body';
        const containerEl = document.querySelector(containerSelector);// 默认获取到body的DOM

        if (!containerEl) {
            throw new Error(`The specified modal container "${containerSelector}" was not found in the DOM.`);
        }

        const activeModal = new PlxActiveModal();
        const contentRef = this._getContentRef(moduleCFR, contentInjector, content, activeModal);

        let windowCmptRef: ComponentRef<PlxModalWindow>;
        let backdropCmptRef: ComponentRef<PlxModalBackdrop>;
        let ngbModalRef: PlxModalRef;


        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);

        /**
         * Attaches a view so that it will be dirty checked.
         * The view will be automatically detached when it is destroyed.
         * This will throw if the view is already attached to a ViewContainer.
         */
        this._applicationRef.attachView(windowCmptRef.hostView);

        containerEl.appendChild(windowCmptRef.location.nativeElement);

        ngbModalRef = new PlxModalRef(windowCmptRef, contentRef, backdropCmptRef);

        activeModal.close = (result: any) => {
            ngbModalRef.close(result);
        };
        activeModal.dismiss = (reason: any) => {
            ngbModalRef.dismiss(reason);
        };

        this._applyWindowOptions(windowCmptRef.instance, options);

        return ngbModalRef;
    }

    private _applyWindowOptions(windowInstance: PlxModalWindow, 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: PlxActiveModal): 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: PlxActiveModal, useValue: context}], contentInjector);
            const componentRef = contentCmptFactory.create(modalContentInjector);
            this._applicationRef.attachView(componentRef.hostView);
            return new ContentRef([[componentRef.location.nativeElement]], componentRef.hostView, componentRef);
        }
    }
}