我正在尝试显示与angular docs中的示例相似(不完全)的动态组件。
我有一个带有viewContainerRef的动态指令
SELECT
name,
SUM(CASE WHEN drunk = 'Y' THEN 1 ELSE 0 END) as drunk,
SUM(CASE WHEN awake = 'Y' THEN 1 ELSE 0 END) as awake
FROM
tb1
GROUP BY
name
摘录组件代码
@Directive({
selector: '[dynamicComponent]'
})
export class DynamicComponentDirective {
constructor(public viewContainerRef: ViewContainerRef) { }
}
最后在模板中添加了@ViewChild(DynamicComponentDirective) adHost: DynamicComponentDirective;
..
ngAfterViewInit() {
let componentFactory = null;
console.log(component);
componentFactory = this.componentFactoryResolver.resolveComponentFactory(component);
// this.adHost.viewContainerRef.clear();
const viewContainerRef = this.adHost.viewContainerRef;
viewContainerRef.createComponent(componentFactory);
}
答案 0 :(得分:14)
你可以采用这种方法:
不要创建指令,而是将ID提供给ng-template
<ng-template #dynamicComponent></ng-template>
在组件类中使用@ViewChild
装饰器
@ViewChild('dynamicComponent', { read: ViewContainerRef }) myRef
ngAfterViewInit() {
const factory = this.componentFactoryResolver.resolveComponentFactory(component);
const ref = this.myRef.createComponent(factory);
ref.changeDetectorRef.detectChanges();
}
答案 1 :(得分:5)
我遇到了同样的问题。您必须将指令添加到AppModule:
@NgModule({
declarations: [
AppComponent,
...,
YourDirective,
],
imports: [
...
],
providers: [...],
bootstrap: [AppComponent],
entryComponents: [components to inject if required]
})
答案 2 :(得分:5)
我也遇到了这个问题,原因是我想将组件动态加载到的位置在ng-if内部(如果最初是隐藏的)。
<div *ngIf="items">
<ng-template appInputHost></ng-template>
</div>
@ViewChild(InputHostDirective, { static: true }) inputHost: InputHostDirective;
将ng-template移到ng-if外部即可解决问题。
答案 3 :(得分:2)
在Angular 8中,我的解决方法是:
@ViewChild('dynamicComponent', {static: true, read: ViewContainerRef}) container: ViewContainerRef;
答案 4 :(得分:0)
请注意,如果指令选择器(在本例中为dynamicComponent)位于:
组件的第一个元素
具有* ngIf条件的父元素
因此,我将其放置在html&load组件的非root标记中,仅在条件匹配时将其放置在viewContainerRef中,以避免出现这种情况。
答案 5 :(得分:0)
问题还可能是viewRef
(在此示例中为dynamicComponent
)的选择器与使用componentFactoryResolver
的组件模板中指定的选择器不匹配。
答案 6 :(得分:0)
当指令未构造时,您会看到此错误。您可以在指令的构造函数上设置一个断点,并检查该断点是否命中。如果不是,则表示您没有正确加载指令。然后,您可以检查正在加载指令的组件是否正确将指令添加到模板中。
答案 7 :(得分:0)
在我的情况下,它是Angular 9,指令的选择器在*ngIf
内部。我使用的解决方案是:
@ViewChild(ExampleDirective, {static: false}) exampleDirectiveHost: ExampleDirective;
由于此处Angular documentation定义的原因,标记static
为假
我做的另一件事是使用
ngAfterViewInit(){
const viewContainerRef = this.exampleDirectiveHost.viewContainerRef;;
}
答案 8 :(得分:0)
模板 HTML 文件:
<ng-template #containerToHostDynamicallyInjectedComponents"></ng-template>
TS 文件
私有组件引用:ComponentRef
@ViewChild('containerToHostDynamicallyInjectedComponents', {read: ViewContainerRef}) hostContainer: ViewContainerRef;
constructor(private componentFactoryResolver:ComponentFactoryResolver) {}
ngOnInit() {
const componentFactory =
this.componentFactoryResolver.resolveComponentFactory(<COMPONENT_NAME_TO_CREATE>);
this.hostContainer.clear(); // CLEAR ANY INJECTED COMPONENT IF EXISTED.
this.componentRef = this.hostContainer.createComponent(componentFactory);
}
```
访问组件的属性和使用方法:
this.componentRef.instance.<PROPERTY_NAME>
this.componentRef.instance.<METHOD_NAME>();
您甚至可以订阅@Output EVENT EMITTERS
this.componentRef.instance.<OUTPUT_PROPERTY_NAME>
.pipe(
take(1)
)
.subscribe(response => console.log(response));