'How do you get the module of a component that's been dynamically loaded in Angular v13?
In v12 you could use the following code to load/import a component dynamically, access its NgModule
through ComponentFactory
and then add it to the DOM using ViewContainerRef
.
const injector: Injector = /* injected */
const cfg: ComponentFactoryResolver = /* injected */
const module = await import('path/to/component/file');
const componentDef = module['MyComponent'];
const cf: ComponentFactory = cfg.resolveComponentFactory(componentDef);
const compModule: NgModuleRef = (cf as any).ngModule;
const container: ViewContainerRef = /*retrieved using @ViewChild*/
container.createComponent(cf, null, injector, compModule)
As of v13 ComponentFactory
(docs) and ComponentFactoryResolver
(docs) are now labeled as deprecated and a new signature has been added to ViewContainerRef.createComponent
which accepts a componentType: Type<C>
as the first argument.
abstract createComponent<C>(componentType: Type<C>, options?: { index?: number; injector?: Injector; ngModuleRef?: NgModuleRef<unknown>; projectableNodes?: Node[][]; }): ComponentRef<C>
So you would now do the following to add a dynamically loaded component to the DOM.
const module = await import('path/to/component/file');
const componentDef = module['MyComponent'];
const container: ViewContainerRef = /*retrieved using @ViewChild*/
container.createComponent(componentDef)
However, the docs for the new signature of ViewContainerRef.createcomponent
show the 2nd optional argument is an object called options
that has an optional property ngModuleRef:NgModuleRef<unknown>
. For which the docs state:
ngModuleRef: an NgModuleRef of the component's NgModule, you should almost always provide this to ensure that all expected providers are available for the component instantiation.
Question
I've struggled to find any example usage of ViewContainerRef.createcomponent
that actually includes a value for ngModuleRef
and with the deprecation of ComponentFactoryResolver
and ComponentFactory
am wondering what the correct/official way to retrieve the module in which the component is declared?
Edit
Just to clarify, i'm interested in whether it's still possible to retrieve the module of a component that's been dynamically loaded using the new method in Angular v13, without explicitly knowing the type of that module?
Solution 1:[1]
In Angular 13+, the solution is to create without using the DEPRECATED compiler.
without using the factory, you have to use ViewContainerRef.createComponent
.
Import injector in constructor
constructor(private _injector: Injector) {}
create module reference using NgModuleRef(ngModule,parentInjector)
const moduleRef: NgModuleRef<T> = createNgModuleRef(module, this._injector);
this.viewRef.createComponent(componentToOpen, {ngModuleRef: moduleRef});
You can also read about all deprecations and possible replacements in the Angular doc https://angular.io/guide/deprecations
Solution 2:[2]
As i'm using single component angular modules (SCAMs) i also have access to the components module when the component file is loaded.
I'm using a naming convention of MyComponent
whose module is named MyComponentModule
so am able to access both the component Class and components NgModule Class using the component name. The NgModule Class can then be passed to createNgModuleRef
to create the instance of NgModuleRef
required for the createComponent
method.
import {createNgModuleRef} from '@angular/core';
const injector: Injector = /* injected */
const compName = 'MyComponent';
const module = await import('path/to/component/file');
const componentClass = module[compName];
const ngModuleRef = createNgModuleRef(module[`${compName}Module`], injector);
const container: ViewContainerRef = /*retrieved using @ViewChild*/
container.createComponent(componentClass, {injector:injector, ngModuleRef:ngModuleRef})
However, this has the drawback of having to have direct access to the components module type, which is not ideal.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Siva Gokul |
Solution 2 |