ngx-bootstrap
Version:
Native Angular Bootstrap Components
244 lines • 10.7 kB
JavaScript
// todo: add delay support
// todo: merge events onShow, onShown, etc...
// todo: add global positioning configuration?
import { ElementRef, EventEmitter, ReflectiveInjector, TemplateRef } from '@angular/core';
import { listenToTriggersV2, registerOutsideClick } from '../utils/triggers';
import { ContentRef } from './content-ref.class';
var ComponentLoader = (function () {
/**
* Do not use this directly, it should be instanced via
* `ComponentLoadFactory.attach`
* @internal
*/
// tslint:disable-next-line
function ComponentLoader(_viewContainerRef, _renderer, _elementRef, _injector, _componentFactoryResolver, _ngZone, _applicationRef, _posService) {
this._viewContainerRef = _viewContainerRef;
this._renderer = _renderer;
this._elementRef = _elementRef;
this._injector = _injector;
this._componentFactoryResolver = _componentFactoryResolver;
this._ngZone = _ngZone;
this._applicationRef = _applicationRef;
this._posService = _posService;
this.onBeforeShow = new EventEmitter();
this.onShown = new EventEmitter();
this.onBeforeHide = new EventEmitter();
this.onHidden = new EventEmitter();
this._providers = [];
this._isHiding = false;
this._listenOpts = {};
this._globalListener = Function.prototype;
}
Object.defineProperty(ComponentLoader.prototype, "isShown", {
get: function () {
if (this._isHiding) {
return false;
}
return !!this._componentRef;
},
enumerable: true,
configurable: true
});
;
ComponentLoader.prototype.attach = function (compType) {
this._componentFactory = this._componentFactoryResolver
.resolveComponentFactory(compType);
return this;
};
// todo: add behaviour: to target element, `body`, custom element
ComponentLoader.prototype.to = function (container) {
this.container = container || this.container;
return this;
};
ComponentLoader.prototype.position = function (opts) {
this.attachment = opts.attachment || this.attachment;
this._elementRef = opts.target || this._elementRef;
return this;
};
ComponentLoader.prototype.provide = function (provider) {
this._providers.push(provider);
return this;
};
// todo: appendChild to element or document.querySelector(this.container)
ComponentLoader.prototype.show = function (opts) {
if (opts === void 0) { opts = {}; }
this._subscribePositioning();
this._innerComponent = null;
if (!this._componentRef) {
this.onBeforeShow.emit();
this._contentRef = this._getContentRef(opts.content);
var injector = ReflectiveInjector.resolveAndCreate(this._providers, this._injector);
this._componentRef = this._componentFactory.create(injector, this._contentRef.nodes);
this._applicationRef.attachView(this._componentRef.hostView);
// this._componentRef = this._viewContainerRef
// .createComponent(this._componentFactory, 0, injector, this._contentRef.nodes);
this.instance = this._componentRef.instance;
Object.assign(this._componentRef.instance, opts);
if (this.container instanceof ElementRef) {
this.container.nativeElement
.appendChild(this._componentRef.location.nativeElement);
}
if (this.container === 'body' && typeof document !== 'undefined') {
document.querySelector(this.container)
.appendChild(this._componentRef.location.nativeElement);
}
if (!this.container && this._elementRef && this._elementRef.nativeElement.parentElement) {
this._elementRef.nativeElement.parentElement
.appendChild(this._componentRef.location.nativeElement);
}
// we need to manually invoke change detection since events registered
// via
// Renderer::listen() are not picked up by change detection with the
// OnPush strategy
if (this._contentRef.componentRef) {
this._innerComponent = this._contentRef.componentRef.instance;
this._contentRef.componentRef.changeDetectorRef.markForCheck();
this._contentRef.componentRef.changeDetectorRef.detectChanges();
}
this._componentRef.changeDetectorRef.markForCheck();
this._componentRef.changeDetectorRef.detectChanges();
this.onShown.emit(this._componentRef.instance);
}
this._registerOutsideClick();
return this._componentRef;
};
ComponentLoader.prototype.hide = function () {
if (!this._componentRef) {
return this;
}
this.onBeforeHide.emit(this._componentRef.instance);
var componentEl = this._componentRef.location.nativeElement;
componentEl.parentNode.removeChild(componentEl);
if (this._contentRef.componentRef) {
this._contentRef.componentRef.destroy();
}
this._componentRef.destroy();
if (this._viewContainerRef && this._contentRef.viewRef) {
this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._contentRef.viewRef));
}
// this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._componentRef.hostView));
//
// if (this._contentRef.viewRef && this._viewContainerRef.indexOf(this._contentRef.viewRef) !== -1) {
// this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._contentRef.viewRef));
// }
this._contentRef = null;
this._componentRef = null;
this._removeGlobalListener();
this.onHidden.emit();
return this;
};
ComponentLoader.prototype.toggle = function () {
if (this.isShown) {
this.hide();
return;
}
this.show();
};
ComponentLoader.prototype.dispose = function () {
if (this.isShown) {
this.hide();
}
this._unsubscribePositioning();
if (this._unregisterListenersFn) {
this._unregisterListenersFn();
}
};
ComponentLoader.prototype.listen = function (listenOpts) {
var _this = this;
this.triggers = listenOpts.triggers || this.triggers;
this._listenOpts.outsideClick = listenOpts.outsideClick;
listenOpts.target = listenOpts.target || this._elementRef.nativeElement;
var hide = this._listenOpts.hide = function () { return listenOpts.hide ? listenOpts.hide() : _this.hide(); };
var show = this._listenOpts.show = function (registerHide) {
listenOpts.show ? listenOpts.show(registerHide) : _this.show(registerHide);
registerHide();
};
var toggle = function (registerHide) {
_this.isShown ? hide() : show(registerHide);
};
this._unregisterListenersFn = listenToTriggersV2(this._renderer, {
target: listenOpts.target,
triggers: listenOpts.triggers,
show: show, hide: hide, toggle: toggle
});
return this;
};
ComponentLoader.prototype._removeGlobalListener = function () {
if (this._globalListener) {
this._globalListener();
this._globalListener = null;
}
};
ComponentLoader.prototype.attachInline = function (vRef, template) {
this._inlineViewRef = vRef.createEmbeddedView(template);
return this;
};
ComponentLoader.prototype._registerOutsideClick = function () {
var _this = this;
if (!this._componentRef || !this._componentRef.location) {
return;
}
// why: should run after first event bubble
var target = this._componentRef.location.nativeElement;
setTimeout(function () {
_this._globalListener = registerOutsideClick(_this._renderer, {
targets: [target, _this._elementRef.nativeElement],
outsideClick: _this._listenOpts.outsideClick,
hide: function () { return _this._listenOpts.hide(); }
});
});
};
ComponentLoader.prototype.getInnerComponent = function () {
return this._innerComponent;
};
ComponentLoader.prototype._subscribePositioning = function () {
var _this = this;
if (this._zoneSubscription || !this.attachment) {
return;
}
this._zoneSubscription = this._ngZone
.onStable.subscribe(function () {
if (!_this._componentRef) {
return;
}
_this._posService.position({
element: _this._componentRef.location,
target: _this._elementRef,
attachment: _this.attachment,
appendToBody: _this.container === 'body'
});
});
};
ComponentLoader.prototype._unsubscribePositioning = function () {
if (!this._zoneSubscription) {
return;
}
this._zoneSubscription.unsubscribe();
this._zoneSubscription = null;
};
ComponentLoader.prototype._getContentRef = function (content) {
if (!content) {
return new ContentRef([]);
}
if (content instanceof TemplateRef) {
if (this._viewContainerRef) {
var viewRef_1 = this._viewContainerRef.createEmbeddedView(content);
return new ContentRef([viewRef_1.rootNodes], viewRef_1);
}
var viewRef = content.createEmbeddedView({});
this._applicationRef.attachView(viewRef);
return new ContentRef([viewRef.rootNodes], viewRef);
}
if (typeof content === 'function') {
var contentCmptFactory = this._componentFactoryResolver.resolveComponentFactory(content);
var modalContentInjector = ReflectiveInjector.resolveAndCreate(this._providers.concat([content]), this._injector);
var componentRef = contentCmptFactory.create(modalContentInjector);
this._applicationRef.attachView(componentRef.hostView);
return new ContentRef([[componentRef.location.nativeElement]], componentRef.hostView, componentRef);
}
return new ContentRef([[this._renderer.createText(null, "" + content)]]);
};
return ComponentLoader;
}());
export { ComponentLoader };
//# sourceMappingURL=component-loader.class.js.map