Skip to content

Commit a9295b3

Browse files
committed
fix(*): removing componentfactory from elements build
1 parent 375b4d8 commit a9295b3

3 files changed

Lines changed: 40 additions & 29 deletions

File tree

projects/igniteui-angular-elements/src/app/create-custom-element.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ function guardAttributeNames<T>(strategyFactory: IgxCustomNgElementStrategyFacto
111111

112112
// getComponentDef not public, also technically readonly map
113113
// the key is the non-minified (template) name
114-
const inputs: {[P in keyof T]: string} = (strategyFactory.componentFactory as any).componentDef.inputs;
114+
const inputs: {[P in keyof T]: string} = (strategyFactory.component as any).ɵcmp.inputs;
115115

116116
for (const key in inputs) {
117117
const input = inputs[key];

projects/igniteui-angular-elements/src/app/custom-strategy.ts

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ApplicationRef, ComponentFactory, ComponentRef, DestroyRef, EventEmitter, Injector, QueryList, Type, ViewContainerRef, reflectComponentType } from '@angular/core';
1+
import { ApplicationRef, ComponentRef, createComponent, DestroyRef, EnvironmentInjector, EventEmitter, Injector, QueryList, Type, ViewContainerRef, reflectComponentType } from '@angular/core';
22
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
33
import { NgElement, NgElementStrategyEvent } from '@angular/elements';
44
import { fromEvent, Observable } from 'rxjs';
@@ -62,12 +62,12 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
6262
}
6363

6464
constructor(
65-
private _componentFactory: ComponentFactory<any>,
65+
private _component: Type<any>,
6666
private _injector: Injector,
6767
private _inputMap: Map<string, string>,
6868
private config: ComponentConfig[],
6969
) {
70-
super(_componentFactory, _injector, _inputMap);
70+
super(_component, _injector, _inputMap);
7171
}
7272

7373
protected override async initializeComponent(element: HTMLElement) {
@@ -82,16 +82,17 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
8282
// set componentRef to non-null to prevent DOM moves from re-initializing
8383
// TODO: Fail handling or cancellation needed?
8484
(this as any).componentRef = {};
85-
const contentChildrenTags = Array.from(element.children).filter(x => this._componentFactory.ngContentSelectors.some(sel => x.matches(sel))).map(x => x.tagName.toLocaleLowerCase());
85+
const ngContentSelectors = reflectComponentType(this._component).ngContentSelectors;
86+
const contentChildrenTags = Array.from(element.children).filter(x => ngContentSelectors.some(sel => x.matches(sel))).map(x => x.tagName.toLocaleLowerCase());
8687

87-
// const toBeOrphanedChildren = Array.from(element.children).filter(x => !this._componentFactory.ngContentSelectors.some(sel => x.matches(sel)));
88+
// const toBeOrphanedChildren = Array.from(element.children).filter(x => !ngContentSelectors.some(sel => x.matches(sel)));
8889
// for (const iterator of toBeOrphanedChildren) {
8990
// // TODO: special registration OR config for custom
9091
// }
9192
let parentInjector: Injector;
9293
let parentAnchor: ViewContainerRef;
9394
const parents: WeakRef<IgcNgElement>[] = [];
94-
const componentConfig = this.config?.find(x => x.component === this._componentFactory.componentType);
95+
const componentConfig = this.config?.find(x => x.component === this._component);
9596

9697
const configParents = componentConfig?.parents
9798
.map(parentType => this.config.find(x => x.component === parentType))
@@ -148,9 +149,14 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
148149
const childInjector = Injector.create({ providers: [], parent: (this as any).injector });
149150
const projectableNodes = extractProjectableNodes(
150151
element,
151-
this._componentFactory.ngContentSelectors,
152+
ngContentSelectors as string[],
152153
);
153-
(this as any).componentRef = this._componentFactory.create(childInjector, projectableNodes, element);
154+
(this as any).componentRef = createComponent(this._component, {
155+
environmentInjector: ((this as any).injector as Injector).get(EnvironmentInjector),
156+
elementInjector: childInjector,
157+
hostElement: element,
158+
projectableNodes,
159+
});
154160
this.setComponentRef((this as any).componentRef);
155161

156162
//we need a name ref on the WC element to be copied down for the purposes of blazor.
@@ -244,7 +250,7 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
244250
return;
245251
}
246252
const componentRef = (this as any).componentRef as ComponentRef<any>;
247-
const componentConfig = this.config?.find(x => x.component === this._componentFactory.componentType);
253+
const componentConfig = this.config?.find(x => x.component === this._component);
248254

249255
if (value === componentRef.instance[property]) {
250256
return;
@@ -290,7 +296,7 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
290296
public override getInputValue(property: string): any {
291297
let returnValue = super.getInputValue(property);
292298

293-
const componentConfig = this.config?.find(x => x.component === this._componentFactory.componentType);
299+
const componentConfig = this.config?.find(x => x.component === this._component);
294300
const componentRef = (this as any).componentRef as ComponentRef<any>;
295301
if (componentRef && componentConfig?.templateProps?.includes(property)) {
296302
returnValue = this.templateWrapper.getTemplateFunction(returnValue) || returnValue;
@@ -319,7 +325,7 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
319325
this.schedule.delete(queryName);
320326
const componentRef = (this as any).componentRef as ComponentRef<any>;
321327
if (componentRef) {
322-
const componentConfig = this.config?.find(x => x.component === this._componentFactory.componentType);
328+
const componentConfig = this.config?.find(x => x.component === this._component);
323329
const query = componentConfig.contentQueries.find(x => x.property === queryName);
324330
const children = this.runQueryInDOM(this.element, query);
325331
let childRefs = [];
@@ -391,7 +397,7 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
391397
continue;
392398
}
393399

394-
const componentType = this._componentFactory.componentType;
400+
const componentType = this._component;
395401
// TODO - look into more cases where query expects a certain base class but gets a subclass.
396402
// Related to https://github.com/IgniteUI/igniteui-angular/pull/12134#discussion_r983147259
397403
const contentQueries = parentConfig.contentQueries.filter(x => x.childType === componentType || x.childType === componentConfig.provideAs);
@@ -454,7 +460,7 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
454460
//#region Handle event args that return reference to components, since they return angular ref and not custom elements.
455461
/** Sets up listeners for the component's outputs so that the events stream emits the events. */
456462
protected override initializeOutputs(componentRef: ComponentRef<any>): void {
457-
const eventEmitters: Observable<NgElementStrategyEvent>[] = this._componentFactory.outputs.map(
463+
const eventEmitters: Observable<NgElementStrategyEvent>[] = reflectComponentType(this._component).outputs.map(
458464
({ propName, templateName }) => {
459465
const emitter: EventEmitter<any> = componentRef.instance[propName];
460466
return emitter.pipe(map((value: any) => ({ name: templateName, value: this.patchOutputComponents(propName, value) })));
@@ -556,6 +562,6 @@ export class IgxCustomNgElementStrategyFactory extends ComponentNgElementStrateg
556562
}
557563

558564
public override create(injector: Injector) {
559-
return new IgxCustomNgElementStrategy(this.componentFactory, injector, this.inputMap, this.config);
565+
return new IgxCustomNgElementStrategy(this.component, injector, this.inputMap, this.config);
560566
}
561567
}

projects/igniteui-angular-elements/src/app/ng-element-strategy.ts

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@
1010

1111
import {
1212
ApplicationRef,
13-
ComponentFactory,
14-
ComponentFactoryResolver,
1513
ComponentRef,
14+
EnvironmentInjector,
1615
EventEmitter,
1716
Injector,
1817
NgZone,
@@ -23,6 +22,8 @@ import {
2322
ɵisViewDirty as isViewDirty,
2423
ɵmarkForRefresh as markForRefresh,
2524
OutputRef,
25+
reflectComponentType,
26+
createComponent,
2627
} from '@angular/core';
2728
import {merge, Observable, ReplaySubject} from 'rxjs';
2829
import {switchMap} from 'rxjs/operators';
@@ -39,25 +40,24 @@ import {
3940
const DESTROY_DELAY = 10;
4041

4142
/**
42-
* Factory that creates new ComponentNgElementStrategy instance. Gets the component factory with the
43-
* constructor's injector's factory resolver and passes that factory to each strategy.
43+
* Factory that creates new ComponentNgElementStrategy instance. Uses reflectComponentType
44+
* to obtain component metadata and passes the component type to each strategy.
4445
*/
4546
export class ComponentNgElementStrategyFactory implements NgElementStrategyFactory {
46-
componentFactory: ComponentFactory<any>;
47+
component: Type<any>;
4748

4849
inputMap = new Map<string, string>();
4950

5051
constructor(component: Type<any>, injector: Injector) {
51-
this.componentFactory = injector
52-
.get(ComponentFactoryResolver)
53-
.resolveComponentFactory(component);
54-
for (const input of this.componentFactory.inputs) {
52+
this.component = component;
53+
const mirror = reflectComponentType(component);
54+
for (const input of mirror.inputs) {
5555
this.inputMap.set(input.propName, input.templateName);
5656
}
5757
}
5858

5959
create(injector: Injector) {
60-
return new ComponentNgElementStrategy(this.componentFactory, injector, this.inputMap);
60+
return new ComponentNgElementStrategy(this.component, injector, this.inputMap);
6161
}
6262
}
6363

@@ -98,7 +98,7 @@ export class ComponentNgElementStrategy implements NgElementStrategy {
9898
private cdScheduler: ChangeDetectionScheduler;
9999

100100
constructor(
101-
private componentFactory: ComponentFactory<any>,
101+
private component: Type<any>,
102102
private injector: Injector,
103103
private inputMap: Map<string, string>,
104104
) {
@@ -200,9 +200,14 @@ export class ComponentNgElementStrategy implements NgElementStrategy {
200200
const childInjector = Injector.create({providers: [], parent: this.injector});
201201
const projectableNodes = extractProjectableNodes(
202202
element,
203-
this.componentFactory.ngContentSelectors,
203+
reflectComponentType(this.component).ngContentSelectors as string[],
204204
);
205-
this.componentRef = this.componentFactory.create(childInjector, projectableNodes, element);
205+
this.componentRef = createComponent(this.component, {
206+
environmentInjector: this.injector.get(EnvironmentInjector),
207+
elementInjector: childInjector,
208+
hostElement: element,
209+
projectableNodes,
210+
});
206211

207212
this.initializeInputs();
208213
this.initializeOutputs(this.componentRef);
@@ -222,7 +227,7 @@ export class ComponentNgElementStrategy implements NgElementStrategy {
222227

223228
/** Sets up listeners for the component's outputs so that the events stream emits the events. */
224229
protected initializeOutputs(componentRef: ComponentRef<any>): void {
225-
const eventEmitters: Observable<NgElementStrategyEvent>[] = this.componentFactory.outputs.map(
230+
const eventEmitters: Observable<NgElementStrategyEvent>[] = reflectComponentType(this.component).outputs.map(
226231
({propName, templateName}) => {
227232
const emitter: EventEmitter<any> | OutputRef<any> = componentRef.instance[propName];
228233
return new Observable((observer) => {

0 commit comments

Comments
 (0)