Last active
February 28, 2019 19:26
-
-
Save wesleygrimes/fc8bd196d896b47debae0c009b6f5709 to your computer and use it in GitHub Desktop.
Dynamic Content Outlet Service
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
ComponentFactoryResolver, | |
ComponentRef, | |
Injectable, | |
Injector, | |
NgModuleFactoryLoader, | |
Type | |
} from '@angular/core'; | |
import { DynamicContentOutletErrorComponent } from './dynamic-content-outlet-error.component'; | |
import { DynamicContentOutletRegistry } from './dynamic-content-outlet.registry'; | |
type ModuleWithDynamicComponents = Type<any> & { | |
dynamicComponentsMap: {}; | |
}; | |
@Injectable() | |
export class DynamicContentOutletService { | |
constructor( | |
private componentFactoryResolver: ComponentFactoryResolver, | |
private moduleLoader: NgModuleFactoryLoader, | |
private injector: Injector | |
) {} | |
async GetComponent(componentName: string): Promise<ComponentRef<any>> { | |
const modulePath = this.getModulePathForComponent(componentName); | |
if (!modulePath) { | |
return this.getDynamicContentErrorComponent( | |
`Unable to derive modulePath from component: ${componentName} in dynamic-content.registry.ts` | |
); | |
} | |
try { | |
const moduleFactory = await this.moduleLoader.load(modulePath); | |
const moduleReference = moduleFactory.create(this.injector); | |
const componentResolver = moduleReference.componentFactoryResolver; | |
const componentType = (moduleFactory.moduleType as ModuleWithDynamicComponents) | |
.dynamicComponentsMap[componentName]; | |
const componentFactory = componentResolver.resolveComponentFactory( | |
componentType | |
); | |
return componentFactory.create(this.injector); | |
} catch (error) { | |
console.error(error.message); | |
return this.getDynamicContentErrorComponent( | |
`Unable to load module ${modulePath}. | |
Looked up using component: ${componentName}. Error Details: ${ | |
error.message | |
}` | |
); | |
} | |
} | |
private getModulePathForComponent(componentName: string) { | |
const registryItem = DynamicContentOutletRegistry.find( | |
i => i.componentName === componentName | |
); | |
if (registryItem && registryItem.modulePath) { | |
// imported modules must be in the format 'path#moduleName' | |
return `${registryItem.modulePath}#${registryItem.moduleName}`; | |
} | |
return null; | |
} | |
private getDynamicContentErrorComponent(errorMessage: string) { | |
const factory = this.componentFactoryResolver.resolveComponentFactory( | |
DynamicContentOutletErrorComponent | |
); | |
const componentRef = factory.create(this.injector); | |
const instance = <any>componentRef.instance; | |
instance.errorMessage = errorMessage; | |
return componentRef; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment