Icard/angular-clarity-master(work.../node_modules/ng-dynamic-component/fesm2020/ng-dynamic-component.mjs

936 lines
40 KiB
JavaScript
Raw Normal View History

2024-07-16 14:55:36 +00:00
import * as i0 from '@angular/core';
import { InjectionToken, Injectable, Injector, Inject, Optional, Directive, Input, Host, NgModule, EventEmitter, Component, Output, ElementRef } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import * as i1 from '@angular/common';
/**
* @public
*/
function defaultEventArgumentFactory() {
return '$event';
}
/**
* @public
*/
const IoEventArgumentToken = new InjectionToken('EventArgument', {
providedIn: 'root',
factory: defaultEventArgumentFactory,
});
/**
* @public
* @deprecated Since v10.4.0 - Use {@link IoEventArgumentToken} instead!
*/
const EventArgumentToken = IoEventArgumentToken;
/**
* A token that holds custom context of the output handlers
*
* @public
*/
const IoEventContextToken = new InjectionToken('IoEventContext');
/**
* A token that holds provider for custom context of the output handlers
* which should be provided using {@link IoEventContextToken} token
*
* @public
*/
const IoEventContextProviderToken = new InjectionToken('IoEventContextProvider');
/**
* @public
*/
const DynamicComponentInjectorToken = new InjectionToken('DynamicComponentInjector');
/**
* @public
*/
class IoServiceOptions {
constructor() {
this.trackOutputChanges = false;
}
}
/** @nocollapse */ IoServiceOptions.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: IoServiceOptions, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
/** @nocollapse */ IoServiceOptions.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: IoServiceOptions, providedIn: 'root' });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: IoServiceOptions, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}] });
/**
* @public
*/
class IoService {
constructor(injector, differs,
// TODO: Replace ComponentFactoryResolver once new API is created
// @see https://github.com/angular/angular/issues/44926
// eslint-disable-next-line deprecation/deprecation
cfr, options, compInjector, eventArgument, cdr, eventContextProvider) {
this.injector = injector;
this.differs = differs;
this.cfr = cfr;
this.options = options;
this.compInjector = compInjector;
this.eventArgument = eventArgument;
this.cdr = cdr;
this.eventContextProvider = eventContextProvider;
this.lastComponentInst = null;
this.lastChangedInputs = new Set();
this.inputsDiffer = this.differs.find({}).create();
// TODO: Replace ComponentFactory once new API is created
// @see https://github.com/angular/angular/issues/44926
// eslint-disable-next-line deprecation/deprecation
this.compFactory = null;
this.outputsShouldDisconnect$ = new Subject();
this.inputs = {};
this.outputs = {};
this.outputsChanged = () => false;
if (this.options.trackOutputChanges) {
const outputsDiffer = this.differs.find({}).create();
this.outputsChanged = (outputs) => !!outputsDiffer.diff(outputs);
}
}
get compRef() {
return this.compInjector.componentRef;
}
get componentInst() {
return this.compRef ? this.compRef.instance : null;
}
get componentInstChanged() {
if (this.lastComponentInst !== this.componentInst) {
this.lastComponentInst = this.componentInst;
return true;
}
else {
return false;
}
}
ngOnDestroy() {
this.disconnectOutputs();
}
/**
* Call update whenever inputs/outputs may or did change.
*
* It will detect both new and mutated changes.
*/
update(inputs, outputs) {
if (!this.compRef) {
this.disconnectOutputs();
return;
}
const changes = this.updateIO(inputs, outputs);
const compChanged = this.componentInstChanged;
const inputsChanges = this.getInputsChanges(compChanged);
const outputsChanged = this.outputsChanged(this.outputs);
if (inputsChanges) {
this.updateChangedInputs(inputsChanges);
}
if (compChanged || inputsChanges) {
this.updateInputs(compChanged || !this.lastChangedInputs.size);
}
if (compChanged || outputsChanged || changes.outputsChanged) {
this.bindOutputs();
}
}
updateIO(inputs, outputs) {
if (!inputs) {
inputs = {};
}
if (!outputs) {
outputs = {};
}
const inputsChanged = this.inputs !== inputs;
const outputsChanged = this.outputs !== outputs;
this.inputs = inputs;
this.outputs = outputs;
return { inputsChanged, outputsChanged };
}
updateInputs(isFirstChange = false) {
if (isFirstChange) {
this.updateCompFactory();
}
const compRef = this.compRef;
const inputs = this.inputs;
if (!inputs || !compRef) {
return;
}
const ifInputChanged = this.lastChangedInputs.size
? (name) => this.lastChangedInputs.has(name)
: () => true;
Object.keys(inputs)
.filter(ifInputChanged)
.forEach((name) => compRef.setInput(name, inputs[name]));
}
bindOutputs() {
this.disconnectOutputs();
const compInst = this.componentInst;
let outputs = this.outputs;
if (!outputs || !compInst) {
return;
}
outputs = this.resolveOutputs(outputs);
Object.keys(outputs)
.filter((p) => compInst[p])
.forEach((p) => compInst[p]
.pipe(takeUntil(this.outputsShouldDisconnect$))
.subscribe((event) => {
this.cdr.markForCheck();
return outputs[p](event);
}));
}
disconnectOutputs() {
this.outputsShouldDisconnect$.next();
}
getInputsChanges(isCompChanged) {
if (isCompChanged) {
this.inputsDiffer.diff({});
}
return this.inputsDiffer.diff(this.inputs);
}
updateChangedInputs(differ) {
this.lastChangedInputs.clear();
const addRecordKeyToSet = (record) => this.lastChangedInputs.add(record.key);
differ.forEachAddedItem(addRecordKeyToSet);
differ.forEachChangedItem(addRecordKeyToSet);
differ.forEachRemovedItem(addRecordKeyToSet);
}
// TODO: Replace ComponentFactory once new API is created
// @see https://github.com/angular/angular/issues/44926
// eslint-disable-next-line deprecation/deprecation
resolveCompFactory() {
if (!this.compRef) {
return null;
}
try {
try {
return this.cfr.resolveComponentFactory(this.compRef.componentType);
}
catch (e) {
// Fallback if componentType does not exist (happens on NgComponentOutlet)
return this.cfr.resolveComponentFactory(this.compRef.instance.constructor);
}
}
catch (e) {
// Factory not available - bailout
return null;
}
}
updateCompFactory() {
this.compFactory = this.resolveCompFactory();
}
resolveOutputs(outputs) {
this.updateOutputsEventContext();
outputs = this.processOutputs(outputs);
if (!this.compFactory) {
return outputs;
}
return this.remapIO(outputs, this.compFactory.outputs);
}
updateOutputsEventContext() {
if (this.eventContextProvider) {
// Resolve custom context from local provider
const eventContextInjector = Injector.create({
name: 'EventContext',
parent: this.injector,
providers: [this.eventContextProvider],
});
this.outputsEventContext = eventContextInjector.get(IoEventContextToken);
}
else {
// Try to get global context
this.outputsEventContext = this.injector.get(IoEventContextToken, null);
}
}
processOutputs(outputs) {
const processedOutputs = {};
Object.keys(outputs).forEach((key) => {
const outputExpr = outputs[key];
let outputHandler;
if (typeof outputExpr === 'function') {
outputHandler = outputExpr;
}
else {
outputHandler = outputExpr && this.processOutputArgs(outputExpr);
}
if (this.outputsEventContext && outputHandler) {
outputHandler = outputHandler.bind(this.outputsEventContext);
}
processedOutputs[key] = outputHandler;
});
return processedOutputs;
}
processOutputArgs(output) {
const eventArgument = this.eventArgument;
const args = 'args' in output ? output.args || [] : [eventArgument];
const eventIdx = args.indexOf(eventArgument);
const handler = output.handler;
// When there is no event argument - use just arguments
if (eventIdx === -1) {
return function () {
return handler.apply(this, args);
};
}
return function (event) {
const argsWithEvent = [...args];
argsWithEvent[eventIdx] = event;
return handler.apply(this, argsWithEvent);
};
}
remapIO(io, mapping) {
const newIO = {};
Object.keys(io).forEach((key) => {
const newKey = this.findPropByTplInMapping(key, mapping) || key;
newIO[newKey] = io[key];
});
return newIO;
}
findPropByTplInMapping(tplName, mapping) {
for (const map of mapping) {
if (map.templateName === tplName) {
return map.propName;
}
}
return null;
}
}
/** @nocollapse */ IoService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: IoService, deps: [{ token: i0.Injector }, { token: i0.KeyValueDiffers }, { token: i0.ComponentFactoryResolver }, { token: IoServiceOptions }, { token: DynamicComponentInjectorToken }, { token: IoEventArgumentToken }, { token: i0.ChangeDetectorRef }, { token: IoEventContextProviderToken, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
/** @nocollapse */ IoService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: IoService });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: IoService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.KeyValueDiffers }, { type: i0.ComponentFactoryResolver }, { type: IoServiceOptions }, { type: undefined, decorators: [{
type: Inject,
args: [DynamicComponentInjectorToken]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [IoEventArgumentToken]
}] }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
type: Inject,
args: [IoEventContextProviderToken]
}, {
type: Optional
}] }]; } });
/**
* @public
*/
class IoFactoryService {
constructor(injector) {
this.injector = injector;
}
create(componentInjector, ioOptions) {
const providers = [
{ provide: IoService, useClass: IoService },
{ provide: DynamicComponentInjectorToken, useValue: componentInjector },
];
if (ioOptions) {
providers.push({ provide: IoServiceOptions, useValue: ioOptions });
}
const ioInjector = Injector.create({
name: 'IoInjector',
parent: ioOptions?.injector ?? this.injector,
providers,
});
return ioInjector.get(IoService);
}
}
/** @nocollapse */ IoFactoryService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: IoFactoryService, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
/** @nocollapse */ IoFactoryService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: IoFactoryService, providedIn: 'root' });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: IoFactoryService, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], ctorParameters: function () { return [{ type: i0.Injector }]; } });
/**
* @public
*/
class ComponentOutletIoDirective {
constructor(ioService) {
this.ioService = ioService;
}
ngDoCheck() {
this.ioService.update(this.ngComponentOutletNdcDynamicInputs, this.ngComponentOutletNdcDynamicOutputs);
}
}
/** @nocollapse */ ComponentOutletIoDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: ComponentOutletIoDirective, deps: [{ token: IoService }], target: i0.ɵɵFactoryTarget.Directive });
/** @nocollapse */ ComponentOutletIoDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.1.3", type: ComponentOutletIoDirective, isStandalone: true, selector: "[ngComponentOutletNdcDynamicInputs],[ngComponentOutletNdcDynamicOutputs]", inputs: { ngComponentOutletNdcDynamicInputs: "ngComponentOutletNdcDynamicInputs", ngComponentOutletNdcDynamicOutputs: "ngComponentOutletNdcDynamicOutputs" }, providers: [IoService], exportAs: ["ndcDynamicIo"], ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: ComponentOutletIoDirective, decorators: [{
type: Directive,
args: [{
selector:
// eslint-disable-next-line @angular-eslint/directive-selector
'[ngComponentOutletNdcDynamicInputs],[ngComponentOutletNdcDynamicOutputs]',
exportAs: 'ndcDynamicIo',
standalone: true,
providers: [IoService],
}]
}], ctorParameters: function () { return [{ type: IoService }]; }, propDecorators: { ngComponentOutletNdcDynamicInputs: [{
type: Input
}], ngComponentOutletNdcDynamicOutputs: [{
type: Input
}] } });
/**
* @public
*/
class ComponentOutletInjectorDirective {
constructor(componentOutlet) {
this.componentOutlet = componentOutlet;
}
get componentRef() {
// NOTE: Accessing private APIs of Angular
return this.componentOutlet._componentRef;
}
}
/** @nocollapse */ ComponentOutletInjectorDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: ComponentOutletInjectorDirective, deps: [{ token: i1.NgComponentOutlet, host: true }], target: i0.ɵɵFactoryTarget.Directive });
/** @nocollapse */ ComponentOutletInjectorDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.1.3", type: ComponentOutletInjectorDirective, isStandalone: true, selector: "[ngComponentOutlet]", providers: [
{
provide: DynamicComponentInjectorToken,
useExisting: ComponentOutletInjectorDirective,
},
], exportAs: ["ndcComponentOutletInjector"], ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: ComponentOutletInjectorDirective, decorators: [{
type: Directive,
args: [{
// eslint-disable-next-line @angular-eslint/directive-selector
selector: '[ngComponentOutlet]',
exportAs: 'ndcComponentOutletInjector',
standalone: true,
providers: [
{
provide: DynamicComponentInjectorToken,
useExisting: ComponentOutletInjectorDirective,
},
],
}]
}], ctorParameters: function () { return [{ type: i1.NgComponentOutlet, decorators: [{
type: Host
}] }]; } });
/**
* @public
*/
class ComponentOutletInjectorModule {
}
/** @nocollapse */ ComponentOutletInjectorModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: ComponentOutletInjectorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
/** @nocollapse */ ComponentOutletInjectorModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.1.3", ngImport: i0, type: ComponentOutletInjectorModule, imports: [ComponentOutletInjectorDirective, ComponentOutletIoDirective], exports: [ComponentOutletInjectorDirective, ComponentOutletIoDirective] });
/** @nocollapse */ ComponentOutletInjectorModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: ComponentOutletInjectorModule });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: ComponentOutletInjectorModule, decorators: [{
type: NgModule,
args: [{
imports: [ComponentOutletInjectorDirective, ComponentOutletIoDirective],
exports: [ComponentOutletInjectorDirective, ComponentOutletIoDirective],
}]
}] });
/**
* @public
*/
class DynamicIoDirective {
constructor(ioService) {
this.ioService = ioService;
}
ngDoCheck() {
this.ioService.update(this.ndcDynamicInputs, this.ndcDynamicOutputs);
}
}
/** @nocollapse */ DynamicIoDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicIoDirective, deps: [{ token: IoService }], target: i0.ɵɵFactoryTarget.Directive });
/** @nocollapse */ DynamicIoDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.1.3", type: DynamicIoDirective, isStandalone: true, selector: "[ndcDynamicInputs],[ndcDynamicOutputs]", inputs: { ndcDynamicInputs: "ndcDynamicInputs", ndcDynamicOutputs: "ndcDynamicOutputs" }, providers: [IoService], exportAs: ["ndcDynamicIo"], ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicIoDirective, decorators: [{
type: Directive,
args: [{
selector: '[ndcDynamicInputs],[ndcDynamicOutputs]',
exportAs: 'ndcDynamicIo',
standalone: true,
providers: [IoService],
}]
}], ctorParameters: function () { return [{ type: IoService }]; }, propDecorators: { ndcDynamicInputs: [{
type: Input
}], ndcDynamicOutputs: [{
type: Input
}] } });
/**
* @public
*/
class DynamicIoModule {
}
/** @nocollapse */ DynamicIoModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicIoModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
/** @nocollapse */ DynamicIoModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.1.3", ngImport: i0, type: DynamicIoModule, imports: [DynamicIoDirective], exports: [DynamicIoDirective, ComponentOutletInjectorModule] });
/** @nocollapse */ DynamicIoModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicIoModule, imports: [ComponentOutletInjectorModule] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicIoModule, decorators: [{
type: NgModule,
args: [{
imports: [DynamicIoDirective],
exports: [DynamicIoDirective, ComponentOutletInjectorModule],
}]
}] });
/**
* @public
*/
class DynamicComponent {
constructor(vcr) {
this.vcr = vcr;
this.ndcDynamicCreated = new EventEmitter();
this.componentRef = null;
}
ngOnChanges(changes) {
if (DynamicComponent.UpdateOnInputs.some((input) => changes.hasOwnProperty(input))) {
this.createDynamicComponent();
}
}
createDynamicComponent() {
this.vcr.clear();
this.componentRef = null;
if (this.ndcDynamicComponent) {
this.componentRef = this.vcr.createComponent(this.ndcDynamicComponent, {
index: 0,
injector: this._resolveInjector(),
projectableNodes: this.ndcDynamicContent,
ngModuleRef: this.ndcDynamicNgModuleRef,
environmentInjector: this.ndcDynamicEnvironmentInjector,
});
this.ndcDynamicCreated.emit(this.componentRef);
}
}
_resolveInjector() {
let injector = this.ndcDynamicInjector || this.vcr.injector;
if (this.ndcDynamicProviders) {
injector = Injector.create({
providers: this.ndcDynamicProviders,
parent: injector,
});
}
return injector;
}
}
DynamicComponent.UpdateOnInputs = [
'ndcDynamicComponent',
'ndcDynamicInjector',
'ndcDynamicProviders',
'ndcDynamicContent',
'ndcDynamicNgModuleRef',
'ndcDynamicEnvironmentInjector',
];
/** @nocollapse */ DynamicComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicComponent, deps: [{ token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ DynamicComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.1.3", type: DynamicComponent, isStandalone: true, selector: "ndc-dynamic", inputs: { ndcDynamicComponent: "ndcDynamicComponent", ndcDynamicInjector: "ndcDynamicInjector", ndcDynamicProviders: "ndcDynamicProviders", ndcDynamicContent: "ndcDynamicContent", ndcDynamicNgModuleRef: "ndcDynamicNgModuleRef", ndcDynamicEnvironmentInjector: "ndcDynamicEnvironmentInjector" }, outputs: { ndcDynamicCreated: "ndcDynamicCreated" }, providers: [
{ provide: DynamicComponentInjectorToken, useExisting: DynamicComponent },
], usesOnChanges: true, ngImport: i0, template: '', isInline: true });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicComponent, decorators: [{
type: Component,
args: [{
selector: 'ndc-dynamic',
standalone: true,
template: '',
providers: [
{ provide: DynamicComponentInjectorToken, useExisting: DynamicComponent },
],
}]
}], ctorParameters: function () { return [{ type: i0.ViewContainerRef }]; }, propDecorators: { ndcDynamicComponent: [{
type: Input
}], ndcDynamicInjector: [{
type: Input
}], ndcDynamicProviders: [{
type: Input
}], ndcDynamicContent: [{
type: Input
}], ndcDynamicNgModuleRef: [{
type: Input
}], ndcDynamicEnvironmentInjector: [{
type: Input
}], ndcDynamicCreated: [{
type: Output
}] } });
/**
* @public
*/
class DynamicModule {
}
/** @nocollapse */ DynamicModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
/** @nocollapse */ DynamicModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.1.3", ngImport: i0, type: DynamicModule, imports: [DynamicIoModule, DynamicComponent], exports: [DynamicIoModule, DynamicComponent] });
/** @nocollapse */ DynamicModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicModule, imports: [DynamicIoModule, DynamicComponent, DynamicIoModule] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicModule, decorators: [{
type: NgModule,
args: [{
imports: [DynamicIoModule, DynamicComponent],
exports: [DynamicIoModule, DynamicComponent],
}]
}] });
/**
* @public
*/
class DynamicAttributesDirective {
constructor(renderer, differs, componentInjector) {
this.renderer = renderer;
this.differs = differs;
this.componentInjector = componentInjector;
this.attrsDiffer = this.differs.find({}).create();
}
get _attributes() {
return (this.ndcDynamicAttributes ||
this.ngComponentOutletNdcDynamicAttributes ||
{});
}
get nativeElement() {
return this.componentInjector?.componentRef?.location.nativeElement;
}
get compType() {
return this.componentInjector?.componentRef?.componentType;
}
get isCompChanged() {
if (this.lastCompType !== this.compType) {
this.lastCompType = this.compType;
return true;
}
return false;
}
ngDoCheck() {
const isCompChanged = this.isCompChanged;
const changes = this.attrsDiffer.diff(this._attributes);
if (changes) {
this.lastAttrActions = this.changesToAttrActions(changes);
}
if (changes || (isCompChanged && this.lastAttrActions)) {
this.updateAttributes(this.lastAttrActions);
}
}
setAttribute(name, value, namespace) {
if (this.nativeElement) {
this.renderer.setAttribute(this.nativeElement, name, value, namespace);
}
}
removeAttribute(name, namespace) {
if (this.nativeElement) {
this.renderer.removeAttribute(this.nativeElement, name, namespace);
}
}
updateAttributes(actions) {
if (!this.compType || !actions) {
return;
}
Object.keys(actions.set).forEach((key) => this.setAttribute(key, actions.set[key]));
actions.remove.forEach((key) => this.removeAttribute(key));
}
changesToAttrActions(changes) {
const attrActions = {
set: {},
remove: [],
};
changes.forEachAddedItem((r) => (attrActions.set[r.key] = r.currentValue));
changes.forEachChangedItem((r) => (attrActions.set[r.key] = r.currentValue));
changes.forEachRemovedItem((r) => attrActions.remove.push(r.key));
return attrActions;
}
}
/** @nocollapse */ DynamicAttributesDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicAttributesDirective, deps: [{ token: i0.Renderer2 }, { token: i0.KeyValueDiffers }, { token: DynamicComponentInjectorToken, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
/** @nocollapse */ DynamicAttributesDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.1.3", type: DynamicAttributesDirective, isStandalone: true, selector: "[ndcDynamicAttributes],[ngComponentOutletNdcDynamicAttributes]", inputs: { ndcDynamicAttributes: "ndcDynamicAttributes", ngComponentOutletNdcDynamicAttributes: "ngComponentOutletNdcDynamicAttributes" }, exportAs: ["ndcDynamicAttributes"], ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicAttributesDirective, decorators: [{
type: Directive,
args: [{
selector: '[ndcDynamicAttributes],[ngComponentOutletNdcDynamicAttributes]',
exportAs: 'ndcDynamicAttributes',
standalone: true,
}]
}], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.KeyValueDiffers }, { type: undefined, decorators: [{
type: Inject,
args: [DynamicComponentInjectorToken]
}, {
type: Optional
}] }]; }, propDecorators: { ndcDynamicAttributes: [{
type: Input
}], ngComponentOutletNdcDynamicAttributes: [{
type: Input
}] } });
/**
* @public
*/
class DynamicAttributesModule {
}
/** @nocollapse */ DynamicAttributesModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicAttributesModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
/** @nocollapse */ DynamicAttributesModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.1.3", ngImport: i0, type: DynamicAttributesModule, imports: [DynamicAttributesDirective], exports: [DynamicAttributesDirective, ComponentOutletInjectorModule] });
/** @nocollapse */ DynamicAttributesModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicAttributesModule, imports: [ComponentOutletInjectorModule] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicAttributesModule, decorators: [{
type: NgModule,
args: [{
imports: [DynamicAttributesDirective],
exports: [DynamicAttributesDirective, ComponentOutletInjectorModule],
}]
}] });
/**
* Extract type arguments from Angular Directive/Component
*
* @internal
*/
function extractNgParamTypes(type) {
// NOTE: Accessing private APIs of Angular
return type?.ctorParameters?.()?.map((param) => param.type);
}
/**
* @internal
*/
function isOnDestroy(obj) {
return !!obj && typeof obj.ngOnDestroy === 'function';
}
/**
* @public
*/
const ReflectRef = new InjectionToken('ReflectRef', {
providedIn: 'root',
factory: () => window.Reflect,
});
/**
* @public
*/
class ReflectService {
constructor(reflect) {
this.reflect = reflect;
}
getCtorParamTypes(ctor) {
return this.reflect.getMetadata('design:paramtypes', ctor);
}
}
/** @nocollapse */ ReflectService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: ReflectService, deps: [{ token: ReflectRef }], target: i0.ɵɵFactoryTarget.Injectable });
/** @nocollapse */ ReflectService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: ReflectService, providedIn: 'root' });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: ReflectService, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Inject,
args: [ReflectRef]
}] }]; } });
/**
* @public
*/
function dynamicDirectiveDef(type, inputs, outputs) {
return { type, inputs, outputs };
}
/**
* @public
* @experimental Dynamic directives is an experimental API that may not work as expected.
*
* NOTE: There is a known issue with OnChanges hook not beign triggered on dynamic directives
* since this part of functionality has been removed from the core as Angular now
* supports this out of the box for dynamic components.
*/
class DynamicDirectivesDirective {
constructor(injector, iterableDiffers, ioFactoryService, reflectService, componentInjector) {
this.injector = injector;
this.iterableDiffers = iterableDiffers;
this.ioFactoryService = ioFactoryService;
this.reflectService = reflectService;
this.componentInjector = componentInjector;
this.ndcDynamicDirectivesCreated = new EventEmitter();
this.dirRef = new Map();
this.dirIo = new Map();
this.dirsDiffer = this.iterableDiffers
.find([])
.create((_, def) => def.type);
}
get directives() {
return (this.ndcDynamicDirectives || this.ngComponentOutletNdcDynamicDirectives);
}
get componentRef() {
return this.componentInjector?.componentRef;
}
get compInstance() {
return this.componentRef && this.componentRef.instance;
}
get isCompChanged() {
if (this.lastCompInstance !== this.compInstance) {
this.lastCompInstance = this.compInstance;
return true;
}
return false;
}
get hostInjector() {
return this.componentRef?.injector;
}
ngDoCheck() {
if (this.maybeDestroyDirectives()) {
return;
}
const dirsChanges = this.dirsDiffer.diff(this.directives);
if (!dirsChanges) {
return this.updateDirectives();
}
this.processDirChanges(dirsChanges);
}
ngOnDestroy() {
this.destroyAllDirectives();
}
maybeDestroyDirectives() {
if (this.isCompChanged || !this.componentRef) {
this.dirsDiffer.diff([]);
this.destroyAllDirectives();
}
return !this.componentRef;
}
processDirChanges(changes) {
changes.forEachRemovedItem(({ item }) => this.destroyDirective(item));
const createdDirs = [];
changes.forEachAddedItem(({ item }) => {
const dirRef = this.initDirective(item);
if (dirRef) {
createdDirs.push(dirRef);
}
});
if (createdDirs.length) {
this.ndcDynamicDirectivesCreated.emit(createdDirs);
}
}
updateDirectives() {
this.directives?.forEach((dir) => this.updateDirective(dir));
}
updateDirective(dirDef) {
const io = this.dirIo.get(dirDef.type);
io?.update(dirDef.inputs, dirDef.outputs);
}
initDirective(dirDef) {
if (this.dirRef.has(dirDef.type)) {
return;
}
const instance = this.createDirective(dirDef.type);
const directiveRef = {
instance,
type: dirDef.type,
injector: this.hostInjector,
hostComponent: this.componentRef.instance,
hostView: this.componentRef.hostView,
location: this.componentRef.location,
changeDetectorRef: this.componentRef.changeDetectorRef,
onDestroy: this.componentRef.onDestroy,
};
this.initDirIO(directiveRef, dirDef);
this.callInitHooks(instance);
this.dirRef.set(directiveRef.type, directiveRef);
return directiveRef;
}
destroyAllDirectives() {
this.dirRef.forEach((dir) => this.destroyDirRef(dir));
this.dirRef.clear();
this.dirIo.clear();
}
destroyDirective(dirDef) {
const dirRef = this.dirRef.get(dirDef.type);
if (dirRef) {
this.destroyDirRef(dirRef);
}
this.dirRef.delete(dirDef.type);
this.dirIo.delete(dirDef.type);
}
initDirIO(dirRef, dirDef) {
const io = this.ioFactoryService.create({ componentRef: this.dirToCompDef(dirRef) }, { trackOutputChanges: true, injector: this.injector });
io.update(dirDef.inputs, dirDef.outputs);
this.dirIo.set(dirRef.type, io);
}
dirToCompDef(dirRef) {
return {
changeDetectorRef: this.componentRef.changeDetectorRef,
hostView: this.componentRef.hostView,
location: this.componentRef.location,
destroy: this.componentRef.destroy,
onDestroy: this.componentRef.onDestroy,
injector: this.componentRef.injector,
instance: dirRef.instance,
componentType: dirRef.type,
setInput: (name, value) => (dirRef.instance[name] = value),
};
}
destroyDirRef(dirRef) {
this.dirIo.get(dirRef.type)?.ngOnDestroy();
if (isOnDestroy(dirRef.instance)) {
dirRef.instance.ngOnDestroy();
}
}
createDirective(dirType) {
const directiveInjector = Injector.create({
providers: [
{
provide: dirType,
useClass: dirType,
deps: this.resolveDirParamTypes(dirType),
},
{ provide: ElementRef, useValue: this.componentRef.location },
],
parent: this.hostInjector,
name: `DynamicDirectiveInjector:${dirType.name}@${this.componentRef.componentType.name}`,
});
return directiveInjector.get(dirType);
}
resolveDirParamTypes(dirType) {
return (
// First try Angular Compiler's metadata
extractNgParamTypes(dirType) ??
// Then fallback to Reflect API
this.reflectService.getCtorParamTypes(dirType) ??
// Bailout
[]);
}
callInitHooks(obj) {
this.callHook(obj, 'ngOnInit');
this.callHook(obj, 'ngDoCheck');
this.callHook(obj, 'ngAfterContentInit');
this.callHook(obj, 'ngAfterContentChecked');
this.callHook(obj, 'ngAfterViewInit');
this.callHook(obj, 'ngAfterViewChecked');
}
callHook(obj, hook, args = []) {
if (obj[hook]) {
obj[hook](...args);
}
}
}
/** @nocollapse */ DynamicDirectivesDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicDirectivesDirective, deps: [{ token: i0.Injector }, { token: i0.IterableDiffers }, { token: IoFactoryService }, { token: ReflectService }, { token: DynamicComponentInjectorToken, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
/** @nocollapse */ DynamicDirectivesDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.1.3", type: DynamicDirectivesDirective, isStandalone: true, selector: "[ndcDynamicDirectives],[ngComponentOutletNdcDynamicDirectives]", inputs: { ndcDynamicDirectives: "ndcDynamicDirectives", ngComponentOutletNdcDynamicDirectives: "ngComponentOutletNdcDynamicDirectives" }, outputs: { ndcDynamicDirectivesCreated: "ndcDynamicDirectivesCreated" }, providers: [IoFactoryService], ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicDirectivesDirective, decorators: [{
type: Directive,
args: [{
selector: '[ndcDynamicDirectives],[ngComponentOutletNdcDynamicDirectives]',
standalone: true,
providers: [IoFactoryService],
}]
}], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.IterableDiffers }, { type: IoFactoryService }, { type: ReflectService }, { type: undefined, decorators: [{
type: Inject,
args: [DynamicComponentInjectorToken]
}, {
type: Optional
}] }]; }, propDecorators: { ndcDynamicDirectives: [{
type: Input
}], ngComponentOutletNdcDynamicDirectives: [{
type: Input
}], ndcDynamicDirectivesCreated: [{
type: Output
}] } });
/**
* @public
*/
class DynamicDirectivesModule {
}
/** @nocollapse */ DynamicDirectivesModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicDirectivesModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
/** @nocollapse */ DynamicDirectivesModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.1.3", ngImport: i0, type: DynamicDirectivesModule, imports: [DynamicDirectivesDirective], exports: [DynamicDirectivesDirective, ComponentOutletInjectorModule] });
/** @nocollapse */ DynamicDirectivesModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicDirectivesModule, imports: [ComponentOutletInjectorModule] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicDirectivesModule, decorators: [{
type: NgModule,
args: [{
imports: [DynamicDirectivesDirective],
exports: [DynamicDirectivesDirective, ComponentOutletInjectorModule],
}]
}] });
/*
* Public API Surface of ng-dynamic-component
*/
/**
* Generated bundle index. Do not edit.
*/
export { ComponentOutletInjectorDirective, ComponentOutletInjectorModule, ComponentOutletIoDirective, DynamicAttributesDirective, DynamicAttributesModule, DynamicComponent, DynamicComponentInjectorToken, DynamicDirectivesDirective, DynamicDirectivesModule, DynamicIoDirective, DynamicIoModule, DynamicModule, EventArgumentToken, IoEventArgumentToken, IoEventContextProviderToken, IoEventContextToken, IoFactoryService, IoService, IoServiceOptions, ReflectRef, ReflectService, defaultEventArgumentFactory, dynamicDirectiveDef };
//# sourceMappingURL=ng-dynamic-component.mjs.map