* Creates a component and applies properties.
( viewContainer: ViewContainerRef, component: Type<T>, props?: Partial<T>, injector?: Injector, outputs?: Record<string, (event: any) => void>, )
| 87 | * Creates a component and applies properties. |
| 88 | */ |
| 89 | function createComponent<T>( |
| 90 | viewContainer: ViewContainerRef, |
| 91 | component: Type<T>, |
| 92 | props?: Partial<T>, |
| 93 | injector?: Injector, |
| 94 | outputs?: Record<string, (event: any) => void>, |
| 95 | ): ComponentRef<T> { |
| 96 | const componentRef = viewContainer.createComponent(component, { |
| 97 | injector, |
| 98 | }); |
| 99 | |
| 100 | if (props) { |
| 101 | // Apply props using setInput, but only for declared inputs |
| 102 | const cmpDef: any = (component as any).ɵcmp; |
| 103 | const declaredInputs = new Set<string>(Object.keys(cmpDef?.inputs ?? {})); |
| 104 | |
| 105 | if (declaredInputs.has("props")) { |
| 106 | componentRef.setInput("props", props as any); |
| 107 | } else { |
| 108 | for (const key in props) { |
| 109 | if (declaredInputs.has(key)) { |
| 110 | const value = (props as any)[key]; |
| 111 | componentRef.setInput(key, value); |
| 112 | } |
| 113 | } |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | if (outputs) { |
| 118 | // Wire up output event handlers with proper cleanup |
| 119 | const instance = componentRef.instance as any; |
| 120 | const subscriptions: any[] = []; |
| 121 | |
| 122 | for (const [eventName, handler] of Object.entries(outputs)) { |
| 123 | if (instance[eventName]?.subscribe) { |
| 124 | const subscription = instance[eventName].subscribe(handler); |
| 125 | subscriptions.push(subscription); |
| 126 | } |
| 127 | } |
| 128 | |
| 129 | // Register cleanup on component destroy |
| 130 | componentRef.onDestroy(() => { |
| 131 | subscriptions.forEach((sub) => sub.unsubscribe()); |
| 132 | }); |
| 133 | } |
| 134 | |
| 135 | // Trigger change detection |
| 136 | componentRef.changeDetectorRef.detectChanges(); |
| 137 | |
| 138 | return componentRef; |
| 139 | } |
| 140 | |
| 141 | /** |
| 142 | * Checks if a value is a component type. |