Question
I'm looking for the best approach for injecting a known/defined component into the root of an application and projecting @Input()
options onto that component.
Requirement
This is necessary for creating things like modals/tooltips in the body of the application so that overflow:hidden
/etc will not distort the position or cut it off completely.
Research
I've found that I can get the ApplicationRef
's and then hackily traverse upwards and find the ViewContainerRef
.
constructor(private applicationRef: ApplicationRef) {
}
getRootViewContainerRef(): ViewContainerRef {
return this.applicationRef['_rootComponents'][0]['_hostElement'].vcRef;
}
once I have that I can then call createComponent
on the ref like:
appendNextToLocation<T>(componentClass: Type<T>, location: ViewContainerRef): ComponentRef<T> {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(componentClass);
const parentInjector = location.parentInjector;
return location.createComponent(componentFactory, location.length, parentInjector);
}
but now I've created the component but none of my Input
properties are fulfilled. To achieve that I have to manually traverse over my options and set those on the result of appendNextToLocation
's instance like:
const props = Object.getOwnPropertyNames(options);
for(const prop of props) {
component.instance[prop] = options[prop];
}
now I do realize you could do some DI to inject the options but that makes it not re-usable when trying to use as a normal component then. Heres what that looks like for reference:
let componentFactory = this.componentFactoryResolver.resolveComponentFactory(ComponentClass);
let parentInjector = location.parentInjector;
let providers = ReflectiveInjector.resolve([
{ provide: ComponentOptionsClass, useValue: options }
]);
childInjector = ReflectiveInjector.fromResolvedProviders(providers, parentInjector);
return location.createComponent(componentFactory, location.length, childInjector);
all that said, all of the above actually works but it feels tad hacky at times. I'm also concerned about lifecycle timing of setting the input properties like the above since it happens after its created.