ngx-bootstrap-component-loader.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. import { Injector, ElementRef, TemplateRef, EventEmitter, Injectable, ComponentFactoryResolver, NgZone, ApplicationRef } from '@angular/core';
  2. import { listenToTriggersV2, registerOutsideClick, registerEscClick } from 'ngx-bootstrap/utils';
  3. import { PositioningService } from 'ngx-bootstrap/positioning';
  4. /**
  5. * @fileoverview added by tsickle
  6. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  7. */
  8. /**
  9. * @template T
  10. */
  11. var /**
  12. * @template T
  13. */
  14. BsComponentRef = /** @class */ (function () {
  15. function BsComponentRef() {
  16. }
  17. return BsComponentRef;
  18. }());
  19. /**
  20. * @fileoverview added by tsickle
  21. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  22. */
  23. /**
  24. * @copyright Valor Software
  25. * @copyright Angular ng-bootstrap team
  26. */
  27. var ContentRef = /** @class */ (function () {
  28. function ContentRef(
  29. /* tslint:disable-next-line: no-any */
  30. nodes, viewRef,
  31. /* tslint:disable-next-line: no-any */
  32. componentRef) {
  33. this.nodes = nodes;
  34. this.viewRef = viewRef;
  35. this.componentRef = componentRef;
  36. }
  37. return ContentRef;
  38. }());
  39. /**
  40. * @fileoverview added by tsickle
  41. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  42. */
  43. /**
  44. * @template T
  45. */
  46. var /**
  47. * @template T
  48. */
  49. ComponentLoader = /** @class */ (function () {
  50. /**
  51. * Do not use this directly, it should be instanced via
  52. * `ComponentLoadFactory.attach`
  53. * @internal
  54. */
  55. // tslint:disable-next-line
  56. function ComponentLoader(_viewContainerRef, _renderer, _elementRef, _injector, _componentFactoryResolver, _ngZone, _applicationRef, _posService) {
  57. this._viewContainerRef = _viewContainerRef;
  58. this._renderer = _renderer;
  59. this._elementRef = _elementRef;
  60. this._injector = _injector;
  61. this._componentFactoryResolver = _componentFactoryResolver;
  62. this._ngZone = _ngZone;
  63. this._applicationRef = _applicationRef;
  64. this._posService = _posService;
  65. this.onBeforeShow = new EventEmitter();
  66. /* tslint:disable-next-line: no-any*/
  67. this.onShown = new EventEmitter();
  68. /* tslint:disable-next-line: no-any*/
  69. this.onBeforeHide = new EventEmitter();
  70. this.onHidden = new EventEmitter();
  71. this._providers = [];
  72. this._isHiding = false;
  73. /**
  74. * A selector used if container element was not found
  75. */
  76. this.containerDefaultSelector = 'body';
  77. this._listenOpts = {};
  78. this._globalListener = Function.prototype;
  79. }
  80. Object.defineProperty(ComponentLoader.prototype, "isShown", {
  81. get: /**
  82. * @return {?}
  83. */
  84. function () {
  85. if (this._isHiding) {
  86. return false;
  87. }
  88. return !!this._componentRef;
  89. },
  90. enumerable: true,
  91. configurable: true
  92. });
  93. /**
  94. * @param {?} compType
  95. * @return {?}
  96. */
  97. ComponentLoader.prototype.attach = /**
  98. * @param {?} compType
  99. * @return {?}
  100. */
  101. function (compType) {
  102. this._componentFactory = this._componentFactoryResolver
  103. .resolveComponentFactory(compType);
  104. return this;
  105. };
  106. // todo: add behaviour: to target element, `body`, custom element
  107. // todo: add behaviour: to target element, `body`, custom element
  108. /**
  109. * @param {?=} container
  110. * @return {?}
  111. */
  112. ComponentLoader.prototype.to =
  113. // todo: add behaviour: to target element, `body`, custom element
  114. /**
  115. * @param {?=} container
  116. * @return {?}
  117. */
  118. function (container) {
  119. this.container = container || this.container;
  120. return this;
  121. };
  122. /**
  123. * @param {?=} opts
  124. * @return {?}
  125. */
  126. ComponentLoader.prototype.position = /**
  127. * @param {?=} opts
  128. * @return {?}
  129. */
  130. function (opts) {
  131. this.attachment = opts.attachment || this.attachment;
  132. /* tslint:disable-next-line: no-unnecessary-type-assertion */
  133. this._elementRef = ((/** @type {?} */ (opts.target))) || this._elementRef;
  134. return this;
  135. };
  136. /**
  137. * @param {?} provider
  138. * @return {?}
  139. */
  140. ComponentLoader.prototype.provide = /**
  141. * @param {?} provider
  142. * @return {?}
  143. */
  144. function (provider) {
  145. this._providers.push(provider);
  146. return this;
  147. };
  148. // todo: appendChild to element or document.querySelector(this.container)
  149. // todo: appendChild to element or document.querySelector(this.container)
  150. /**
  151. * @param {?=} opts
  152. * @return {?}
  153. */
  154. ComponentLoader.prototype.show =
  155. // todo: appendChild to element or document.querySelector(this.container)
  156. /**
  157. * @param {?=} opts
  158. * @return {?}
  159. */
  160. function (opts) {
  161. if (opts === void 0) { opts = {}; }
  162. this._subscribePositioning();
  163. this._innerComponent = null;
  164. if (!this._componentRef) {
  165. this.onBeforeShow.emit();
  166. this._contentRef = this._getContentRef(opts.content, opts.context, opts.initialState);
  167. /** @type {?} */
  168. var injector = Injector.create({
  169. providers: this._providers,
  170. parent: this._injector
  171. });
  172. this._componentRef = this._componentFactory.create(injector, this._contentRef.nodes);
  173. this._applicationRef.attachView(this._componentRef.hostView);
  174. // this._componentRef = this._viewContainerRef
  175. // .createComponent(this._componentFactory, 0, injector, this._contentRef.nodes);
  176. this.instance = this._componentRef.instance;
  177. Object.assign(this._componentRef.instance, opts);
  178. if (this.container instanceof ElementRef) {
  179. this.container.nativeElement.appendChild(this._componentRef.location.nativeElement);
  180. }
  181. if (typeof this.container === 'string' && typeof document !== 'undefined') {
  182. /** @type {?} */
  183. var selectedElement = document.querySelector(this.container) ||
  184. document.querySelector(this.containerDefaultSelector);
  185. selectedElement.appendChild(this._componentRef.location.nativeElement);
  186. }
  187. if (!this.container &&
  188. this._elementRef &&
  189. this._elementRef.nativeElement.parentElement) {
  190. this._elementRef.nativeElement.parentElement.appendChild(this._componentRef.location.nativeElement);
  191. }
  192. // we need to manually invoke change detection since events registered
  193. // via
  194. // Renderer::listen() are not picked up by change detection with the
  195. // OnPush strategy
  196. if (this._contentRef.componentRef) {
  197. this._innerComponent = this._contentRef.componentRef.instance;
  198. this._contentRef.componentRef.changeDetectorRef.markForCheck();
  199. this._contentRef.componentRef.changeDetectorRef.detectChanges();
  200. }
  201. this._componentRef.changeDetectorRef.markForCheck();
  202. this._componentRef.changeDetectorRef.detectChanges();
  203. this.onShown.emit(this._componentRef.instance);
  204. }
  205. this._registerOutsideClick();
  206. return this._componentRef;
  207. };
  208. /**
  209. * @return {?}
  210. */
  211. ComponentLoader.prototype.hide = /**
  212. * @return {?}
  213. */
  214. function () {
  215. if (!this._componentRef) {
  216. return this;
  217. }
  218. this._posService.deletePositionElement(this._componentRef.location);
  219. this.onBeforeHide.emit(this._componentRef.instance);
  220. /** @type {?} */
  221. var componentEl = this._componentRef.location.nativeElement;
  222. componentEl.parentNode.removeChild(componentEl);
  223. if (this._contentRef.componentRef) {
  224. this._contentRef.componentRef.destroy();
  225. }
  226. this._componentRef.destroy();
  227. if (this._viewContainerRef && this._contentRef.viewRef) {
  228. this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._contentRef.viewRef));
  229. }
  230. if (this._contentRef.viewRef) {
  231. this._contentRef.viewRef.destroy();
  232. }
  233. this._contentRef = null;
  234. this._componentRef = null;
  235. this._removeGlobalListener();
  236. this.onHidden.emit();
  237. return this;
  238. };
  239. /**
  240. * @return {?}
  241. */
  242. ComponentLoader.prototype.toggle = /**
  243. * @return {?}
  244. */
  245. function () {
  246. if (this.isShown) {
  247. this.hide();
  248. return;
  249. }
  250. this.show();
  251. };
  252. /**
  253. * @return {?}
  254. */
  255. ComponentLoader.prototype.dispose = /**
  256. * @return {?}
  257. */
  258. function () {
  259. if (this.isShown) {
  260. this.hide();
  261. }
  262. this._unsubscribePositioning();
  263. if (this._unregisterListenersFn) {
  264. this._unregisterListenersFn();
  265. }
  266. };
  267. /**
  268. * @param {?} listenOpts
  269. * @return {?}
  270. */
  271. ComponentLoader.prototype.listen = /**
  272. * @param {?} listenOpts
  273. * @return {?}
  274. */
  275. function (listenOpts) {
  276. var _this = this;
  277. this.triggers = listenOpts.triggers || this.triggers;
  278. this._listenOpts.outsideClick = listenOpts.outsideClick;
  279. this._listenOpts.outsideEsc = listenOpts.outsideEsc;
  280. listenOpts.target = listenOpts.target || this._elementRef.nativeElement;
  281. /** @type {?} */
  282. var hide = (this._listenOpts.hide = (/**
  283. * @return {?}
  284. */
  285. function () {
  286. return listenOpts.hide ? listenOpts.hide() : void _this.hide();
  287. }));
  288. /** @type {?} */
  289. var show = (this._listenOpts.show = (/**
  290. * @param {?} registerHide
  291. * @return {?}
  292. */
  293. function (registerHide) {
  294. listenOpts.show ? listenOpts.show(registerHide) : _this.show(registerHide);
  295. registerHide();
  296. }));
  297. /** @type {?} */
  298. var toggle = (/**
  299. * @param {?} registerHide
  300. * @return {?}
  301. */
  302. function (registerHide) {
  303. _this.isShown ? hide() : show(registerHide);
  304. });
  305. this._unregisterListenersFn = listenToTriggersV2(this._renderer, {
  306. target: listenOpts.target,
  307. triggers: listenOpts.triggers,
  308. show: show,
  309. hide: hide,
  310. toggle: toggle
  311. });
  312. return this;
  313. };
  314. /**
  315. * @return {?}
  316. */
  317. ComponentLoader.prototype._removeGlobalListener = /**
  318. * @return {?}
  319. */
  320. function () {
  321. if (this._globalListener) {
  322. this._globalListener();
  323. this._globalListener = null;
  324. }
  325. };
  326. /**
  327. * @param {?} vRef
  328. * @param {?} template
  329. * @return {?}
  330. */
  331. ComponentLoader.prototype.attachInline = /**
  332. * @param {?} vRef
  333. * @param {?} template
  334. * @return {?}
  335. */
  336. function (vRef,
  337. /* tslint:disable-next-line: no-any*/
  338. template) {
  339. this._inlineViewRef = vRef.createEmbeddedView(template);
  340. return this;
  341. };
  342. /**
  343. * @return {?}
  344. */
  345. ComponentLoader.prototype._registerOutsideClick = /**
  346. * @return {?}
  347. */
  348. function () {
  349. var _this = this;
  350. if (!this._componentRef || !this._componentRef.location) {
  351. return;
  352. }
  353. // why: should run after first event bubble
  354. if (this._listenOpts.outsideClick) {
  355. /** @type {?} */
  356. var target_1 = this._componentRef.location.nativeElement;
  357. setTimeout((/**
  358. * @return {?}
  359. */
  360. function () {
  361. _this._globalListener = registerOutsideClick(_this._renderer, {
  362. targets: [target_1, _this._elementRef.nativeElement],
  363. outsideClick: _this._listenOpts.outsideClick,
  364. hide: (/**
  365. * @return {?}
  366. */
  367. function () { return _this._listenOpts.hide(); })
  368. });
  369. }));
  370. }
  371. if (this._listenOpts.outsideEsc) {
  372. /** @type {?} */
  373. var target = this._componentRef.location.nativeElement;
  374. this._globalListener = registerEscClick(this._renderer, {
  375. targets: [target, this._elementRef.nativeElement],
  376. outsideEsc: this._listenOpts.outsideEsc,
  377. hide: (/**
  378. * @return {?}
  379. */
  380. function () { return _this._listenOpts.hide(); })
  381. });
  382. }
  383. };
  384. /**
  385. * @return {?}
  386. */
  387. ComponentLoader.prototype.getInnerComponent = /**
  388. * @return {?}
  389. */
  390. function () {
  391. return this._innerComponent;
  392. };
  393. /**
  394. * @private
  395. * @return {?}
  396. */
  397. ComponentLoader.prototype._subscribePositioning = /**
  398. * @private
  399. * @return {?}
  400. */
  401. function () {
  402. var _this = this;
  403. if (this._zoneSubscription || !this.attachment) {
  404. return;
  405. }
  406. this.onShown.subscribe((/**
  407. * @return {?}
  408. */
  409. function () {
  410. _this._posService.position({
  411. element: _this._componentRef.location,
  412. target: _this._elementRef,
  413. attachment: _this.attachment,
  414. appendToBody: _this.container === 'body'
  415. });
  416. }));
  417. this._zoneSubscription = this._ngZone.onStable.subscribe((/**
  418. * @return {?}
  419. */
  420. function () {
  421. if (!_this._componentRef) {
  422. return;
  423. }
  424. _this._posService.calcPosition();
  425. }));
  426. };
  427. /**
  428. * @private
  429. * @return {?}
  430. */
  431. ComponentLoader.prototype._unsubscribePositioning = /**
  432. * @private
  433. * @return {?}
  434. */
  435. function () {
  436. if (!this._zoneSubscription) {
  437. return;
  438. }
  439. this._zoneSubscription.unsubscribe();
  440. this._zoneSubscription = null;
  441. };
  442. /**
  443. * @private
  444. * @param {?} content
  445. * @param {?=} context
  446. * @param {?=} initialState
  447. * @return {?}
  448. */
  449. ComponentLoader.prototype._getContentRef = /**
  450. * @private
  451. * @param {?} content
  452. * @param {?=} context
  453. * @param {?=} initialState
  454. * @return {?}
  455. */
  456. function (
  457. /* tslint:disable-next-line: no-any*/
  458. content,
  459. /* tslint:disable-next-line: no-any*/
  460. context,
  461. /* tslint:disable-next-line: no-any*/
  462. initialState) {
  463. if (!content) {
  464. return new ContentRef([]);
  465. }
  466. if (content instanceof TemplateRef) {
  467. if (this._viewContainerRef) {
  468. /** @type {?} */
  469. var _viewRef = this._viewContainerRef
  470. .createEmbeddedView(content, context);
  471. _viewRef.markForCheck();
  472. return new ContentRef([_viewRef.rootNodes], _viewRef);
  473. }
  474. /** @type {?} */
  475. var viewRef = content.createEmbeddedView({});
  476. this._applicationRef.attachView(viewRef);
  477. return new ContentRef([viewRef.rootNodes], viewRef);
  478. }
  479. if (typeof content === 'function') {
  480. /** @type {?} */
  481. var contentCmptFactory = this._componentFactoryResolver.resolveComponentFactory(content);
  482. /** @type {?} */
  483. var modalContentInjector = Injector.create({
  484. providers: this._providers,
  485. parent: this._injector
  486. });
  487. /** @type {?} */
  488. var componentRef = contentCmptFactory.create(modalContentInjector);
  489. Object.assign(componentRef.instance, initialState);
  490. this._applicationRef.attachView(componentRef.hostView);
  491. return new ContentRef([[componentRef.location.nativeElement]], componentRef.hostView, componentRef);
  492. }
  493. return new ContentRef([[this._renderer.createText("" + content)]]);
  494. };
  495. return ComponentLoader;
  496. }());
  497. /**
  498. * @fileoverview added by tsickle
  499. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  500. */
  501. var ComponentLoaderFactory = /** @class */ (function () {
  502. function ComponentLoaderFactory(_componentFactoryResolver, _ngZone, _injector, _posService, _applicationRef) {
  503. this._componentFactoryResolver = _componentFactoryResolver;
  504. this._ngZone = _ngZone;
  505. this._injector = _injector;
  506. this._posService = _posService;
  507. this._applicationRef = _applicationRef;
  508. }
  509. /**
  510. *
  511. * @param _elementRef
  512. * @param _viewContainerRef
  513. * @param _renderer
  514. */
  515. /**
  516. *
  517. * @template T
  518. * @param {?} _elementRef
  519. * @param {?} _viewContainerRef
  520. * @param {?} _renderer
  521. * @return {?}
  522. */
  523. ComponentLoaderFactory.prototype.createLoader = /**
  524. *
  525. * @template T
  526. * @param {?} _elementRef
  527. * @param {?} _viewContainerRef
  528. * @param {?} _renderer
  529. * @return {?}
  530. */
  531. function (_elementRef, _viewContainerRef, _renderer) {
  532. return new ComponentLoader(_viewContainerRef, _renderer, _elementRef, this._injector, this._componentFactoryResolver, this._ngZone, this._applicationRef, this._posService);
  533. };
  534. ComponentLoaderFactory.decorators = [
  535. { type: Injectable }
  536. ];
  537. /** @nocollapse */
  538. ComponentLoaderFactory.ctorParameters = function () { return [
  539. { type: ComponentFactoryResolver },
  540. { type: NgZone },
  541. { type: Injector },
  542. { type: PositioningService },
  543. { type: ApplicationRef }
  544. ]; };
  545. return ComponentLoaderFactory;
  546. }());
  547. export { BsComponentRef, ComponentLoader, ComponentLoaderFactory, ContentRef };
  548. //# sourceMappingURL=ngx-bootstrap-component-loader.js.map