1 |
|
2 |
|
3 |
|
4 | import { ElementRef, EventEmitter, Injector, TemplateRef } from '@angular/core';
|
5 | import { listenToTriggersV2, registerEscClick, registerOutsideClick } from 'ngx-bootstrap/utils';
|
6 | import { ContentRef } from './content-ref.class';
|
7 | export class ComponentLoader {
|
8 | |
9 |
|
10 |
|
11 |
|
12 |
|
13 | constructor(_viewContainerRef, _renderer, _elementRef, _injector, _componentFactoryResolver, _ngZone, _applicationRef, _posService) {
|
14 | this._viewContainerRef = _viewContainerRef;
|
15 | this._renderer = _renderer;
|
16 | this._elementRef = _elementRef;
|
17 | this._injector = _injector;
|
18 | this._componentFactoryResolver = _componentFactoryResolver;
|
19 | this._ngZone = _ngZone;
|
20 | this._applicationRef = _applicationRef;
|
21 | this._posService = _posService;
|
22 | this.onBeforeShow = new EventEmitter();
|
23 | this.onShown = new EventEmitter();
|
24 | this.onBeforeHide = new EventEmitter();
|
25 | this.onHidden = new EventEmitter();
|
26 | this._providers = [];
|
27 | this._isHiding = false;
|
28 | |
29 |
|
30 |
|
31 | this.containerDefaultSelector = 'body';
|
32 | this._listenOpts = {};
|
33 | this._globalListener = Function.prototype;
|
34 | }
|
35 | get isShown() {
|
36 | if (this._isHiding) {
|
37 | return false;
|
38 | }
|
39 | return !!this._componentRef;
|
40 | }
|
41 | attach(compType) {
|
42 | this._componentFactory = this._componentFactoryResolver
|
43 | .resolveComponentFactory(compType);
|
44 | return this;
|
45 | }
|
46 |
|
47 | to(container) {
|
48 | this.container = container || this.container;
|
49 | return this;
|
50 | }
|
51 | position(opts) {
|
52 | if (!opts) {
|
53 | return this;
|
54 | }
|
55 | this.attachment = opts.attachment || this.attachment;
|
56 | this._elementRef = opts.target || this._elementRef;
|
57 | return this;
|
58 | }
|
59 | provide(provider) {
|
60 | this._providers.push(provider);
|
61 | return this;
|
62 | }
|
63 |
|
64 | show(opts = {}) {
|
65 | this._subscribePositioning();
|
66 | this._innerComponent = void 0;
|
67 | if (!this._componentRef) {
|
68 | this.onBeforeShow.emit();
|
69 | this._contentRef = this._getContentRef(opts.content, opts.context, opts.initialState);
|
70 | const injector = Injector.create({
|
71 | providers: this._providers,
|
72 | parent: this._injector
|
73 | });
|
74 | if (!this._componentFactory) {
|
75 | return;
|
76 | }
|
77 | this._componentRef = this._componentFactory.create(injector, this._contentRef.nodes);
|
78 | this._applicationRef.attachView(this._componentRef.hostView);
|
79 |
|
80 |
|
81 | this.instance = this._componentRef.instance;
|
82 | Object.assign(this._componentRef.instance, opts);
|
83 | if (this.container instanceof ElementRef) {
|
84 | this.container.nativeElement.appendChild(this._componentRef.location.nativeElement);
|
85 | }
|
86 | if (typeof this.container === 'string' && typeof document !== 'undefined') {
|
87 | const selectedElement = document.querySelector(this.container) ||
|
88 | document.querySelector(this.containerDefaultSelector);
|
89 | if (!selectedElement) {
|
90 | return;
|
91 | }
|
92 | selectedElement.appendChild(this._componentRef.location.nativeElement);
|
93 | }
|
94 | if (!this.container &&
|
95 | this._elementRef &&
|
96 | this._elementRef.nativeElement.parentElement) {
|
97 | this._elementRef.nativeElement.parentElement.appendChild(this._componentRef.location.nativeElement);
|
98 | }
|
99 |
|
100 |
|
101 |
|
102 |
|
103 | if (this._contentRef.componentRef) {
|
104 | this._innerComponent = this._contentRef.componentRef.instance;
|
105 | this._contentRef.componentRef.changeDetectorRef.markForCheck();
|
106 | this._contentRef.componentRef.changeDetectorRef.detectChanges();
|
107 | }
|
108 | this._componentRef.changeDetectorRef.markForCheck();
|
109 | this._componentRef.changeDetectorRef.detectChanges();
|
110 | this.onShown.emit(opts.id ? { id: opts.id } : this._componentRef.instance);
|
111 | }
|
112 | this._registerOutsideClick();
|
113 | return this._componentRef;
|
114 | }
|
115 | hide(id) {
|
116 | var _a, _b, _c;
|
117 | if (!this._componentRef) {
|
118 | return this;
|
119 | }
|
120 | this._posService.deletePositionElement(this._componentRef.location);
|
121 | this.onBeforeHide.emit(this._componentRef.instance);
|
122 | const componentEl = this._componentRef.location.nativeElement;
|
123 | componentEl.parentNode.removeChild(componentEl);
|
124 | if ((_a = this._contentRef) === null || _a === void 0 ? void 0 : _a.componentRef) {
|
125 | this._contentRef.componentRef.destroy();
|
126 | }
|
127 | if (this._viewContainerRef && ((_b = this._contentRef) === null || _b === void 0 ? void 0 : _b.viewRef)) {
|
128 | this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._contentRef.viewRef));
|
129 | }
|
130 | if ((_c = this._contentRef) === null || _c === void 0 ? void 0 : _c.viewRef) {
|
131 | this._contentRef.viewRef.destroy();
|
132 | }
|
133 | this._contentRef = void 0;
|
134 | this._componentRef = void 0;
|
135 | this._removeGlobalListener();
|
136 | this.onHidden.emit(id ? { id } : null);
|
137 | return this;
|
138 | }
|
139 | toggle() {
|
140 | if (this.isShown) {
|
141 | this.hide();
|
142 | return;
|
143 | }
|
144 | this.show();
|
145 | }
|
146 | dispose() {
|
147 | if (this.isShown) {
|
148 | this.hide();
|
149 | }
|
150 | this._unsubscribePositioning();
|
151 | if (this._unregisterListenersFn) {
|
152 | this._unregisterListenersFn();
|
153 | }
|
154 | }
|
155 | listen(listenOpts) {
|
156 | var _a;
|
157 | this.triggers = listenOpts.triggers || this.triggers;
|
158 | this._listenOpts.outsideClick = listenOpts.outsideClick;
|
159 | this._listenOpts.outsideEsc = listenOpts.outsideEsc;
|
160 | listenOpts.target = listenOpts.target || ((_a = this._elementRef) === null || _a === void 0 ? void 0 : _a.nativeElement);
|
161 | const hide = (this._listenOpts.hide = () => listenOpts.hide ? listenOpts.hide() : void this.hide());
|
162 | const show = (this._listenOpts.show = (registerHide) => {
|
163 | listenOpts.show ? listenOpts.show(registerHide) : this.show(registerHide);
|
164 | registerHide();
|
165 | });
|
166 |
|
167 | const toggle = (registerHide) => {
|
168 | this.isShown ? hide() : show(registerHide);
|
169 | };
|
170 | if (this._renderer) {
|
171 | this._unregisterListenersFn = listenToTriggersV2(this._renderer, {
|
172 | target: listenOpts.target,
|
173 | triggers: listenOpts.triggers,
|
174 | show,
|
175 | hide,
|
176 | toggle
|
177 | });
|
178 | }
|
179 | return this;
|
180 | }
|
181 | _removeGlobalListener() {
|
182 | if (this._globalListener) {
|
183 | this._globalListener();
|
184 | this._globalListener = Function.prototype;
|
185 | }
|
186 | }
|
187 | attachInline(vRef,
|
188 |
|
189 | template) {
|
190 | if (vRef && template) {
|
191 | this._inlineViewRef = vRef.createEmbeddedView(template);
|
192 | }
|
193 | return this;
|
194 | }
|
195 | _registerOutsideClick() {
|
196 | if (!this._componentRef || !this._componentRef.location) {
|
197 | return;
|
198 | }
|
199 |
|
200 | if (this._listenOpts.outsideClick) {
|
201 | const target = this._componentRef.location.nativeElement;
|
202 | setTimeout(() => {
|
203 | if (this._renderer && this._elementRef) {
|
204 | this._globalListener = registerOutsideClick(this._renderer, {
|
205 | targets: [target, this._elementRef.nativeElement],
|
206 | outsideClick: this._listenOpts.outsideClick,
|
207 | hide: () => this._listenOpts.hide && this._listenOpts.hide()
|
208 | });
|
209 | }
|
210 | });
|
211 | }
|
212 | if (this._listenOpts.outsideEsc && this._renderer && this._elementRef) {
|
213 | const target = this._componentRef.location.nativeElement;
|
214 | this._globalListener = registerEscClick(this._renderer, {
|
215 | targets: [target, this._elementRef.nativeElement],
|
216 | outsideEsc: this._listenOpts.outsideEsc,
|
217 | hide: () => this._listenOpts.hide && this._listenOpts.hide()
|
218 | });
|
219 | }
|
220 | }
|
221 | getInnerComponent() {
|
222 | return this._innerComponent;
|
223 | }
|
224 | _subscribePositioning() {
|
225 | if (this._zoneSubscription || !this.attachment) {
|
226 | return;
|
227 | }
|
228 | this.onShown.subscribe(() => {
|
229 | var _a;
|
230 | this._posService.position({
|
231 | element: (_a = this._componentRef) === null || _a === void 0 ? void 0 : _a.location,
|
232 | target: this._elementRef,
|
233 | attachment: this.attachment,
|
234 | appendToBody: this.container === 'body'
|
235 | });
|
236 | });
|
237 | this._zoneSubscription = this._ngZone.onStable.subscribe(() => {
|
238 | if (!this._componentRef) {
|
239 | return;
|
240 | }
|
241 | this._posService.calcPosition();
|
242 | });
|
243 | }
|
244 | _unsubscribePositioning() {
|
245 | if (!this._zoneSubscription) {
|
246 | return;
|
247 | }
|
248 | this._zoneSubscription.unsubscribe();
|
249 | this._zoneSubscription = void 0;
|
250 | }
|
251 | _getContentRef(
|
252 |
|
253 | content,
|
254 |
|
255 | context,
|
256 |
|
257 | initialState) {
|
258 | if (!content) {
|
259 | return new ContentRef([]);
|
260 | }
|
261 | if (content instanceof TemplateRef) {
|
262 | if (this._viewContainerRef) {
|
263 | const _viewRef = this._viewContainerRef
|
264 | .createEmbeddedView(content, context);
|
265 | _viewRef.markForCheck();
|
266 | return new ContentRef([_viewRef.rootNodes], _viewRef);
|
267 | }
|
268 | const viewRef = content.createEmbeddedView({});
|
269 | this._applicationRef.attachView(viewRef);
|
270 | return new ContentRef([viewRef.rootNodes], viewRef);
|
271 | }
|
272 | if (typeof content === 'function') {
|
273 | const contentCmptFactory = this._componentFactoryResolver.resolveComponentFactory(content);
|
274 | const modalContentInjector = Injector.create({
|
275 | providers: this._providers,
|
276 | parent: this._injector
|
277 | });
|
278 | const componentRef = contentCmptFactory.create(modalContentInjector);
|
279 | Object.assign(componentRef.instance, initialState);
|
280 | this._applicationRef.attachView(componentRef.hostView);
|
281 | return new ContentRef([[componentRef.location.nativeElement]], componentRef.hostView, componentRef);
|
282 | }
|
283 | const nodes = this._renderer
|
284 | ? [this._renderer.createText(`${content}`)]
|
285 | : [];
|
286 | return new ContentRef([nodes]);
|
287 | }
|
288 | }
|
289 |
|
\ | No newline at end of file |