问题
我正在寻找将已知/定义的组件注入应用程序根部并将 @Input()
选项投射到该组件的最佳方法。
要求
这对于在应用程序主体中创建诸如模态框/工具提示之类的内容是必要的,以便 overflow:hidden
/等不会扭曲其位置或完全截断它。
研究
我发现我可以获取 ApplicationRef
,然后通过 hackily 向上遍历并找到 ViewContainerRef
。
constructor(private applicationRef: ApplicationRef) {
}
getRootViewContainerRef(): ViewContainerRef {
return this.applicationRef['_rootComponents'][0]['_hostElement'].vcRef;
}
有了这个后,我可以在该引用上调用createComponent
方法:
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);
}
但是现在我已经创建了组件,但是我的Input
属性都没有被满足。为了实现这一点,我必须手动遍历我的选项,并将它们设置在appendNextToLocation
实例的结果上,例如:
但现在我已经创建了组件,但我的Input
属性尚未填充。为了实现此目的,我需要手动遍历我的选项并将它们设置在appendNextToLocation
实例的结果上,如下所示:
const props = Object.getOwnPropertyNames(options);
for(const prop of props) {
component.instance[prop] = options[prop];
}
现在我意识到您可以进行一些 DI 来注入选项,但这样做会使其在尝试将其用作普通组件时无法重复使用。以下是参考:
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);
虽然上述方法都能达到预期效果,但有时会感觉有些hacky。我也担心像上述那样设置输入属性的生命周期时机,因为它是在创建后发生的。