[英]ngOnInit is not called on dynamic component
I'm using Angular 8 for a project, and I'm having trouble launching a dynamic component because ngOnInit doesn't get called.我在一个项目中使用 Angular 8,但我在启动动态组件时遇到了问题,因为 ngOnInit 没有被调用。 I've build a directive called PlaceholderDirective, shown below:
我已经构建了一个名为 PlaceholderDirective 的指令,如下所示:
@Directive({
selector: '[appPlaceholder]'
})
export class PlaceholderDirective {
constructor(public viewContainerRef: ViewContainerRef) {}
}
And used that directive on a ng-template:并在 ng-template 上使用该指令:
<ng-template appPlaceholder></ng-template>
The component that holds the HTML where the ng-template lies launches the dynamic component, as such:包含 ng-template 所在 HTML 的组件启动动态组件,如下所示:
@ViewChild(PlaceholderDirective, {static: false}) private placeholder: PlaceholderDirective;
...
constructor(private componentResolver: ComponentFactoryResolver) {}
...
public launchSensorEditComponent(id: number) {
const componentFactory = this.componentResolver.resolveComponentFactory(SensorEditComponent);
const hostViewContainerRef = this.placeholder.viewContainerRef;
hostViewContainerRef.clear();
const sensorEditComponentRef = hostViewContainerRef.createComponent(componentFactory);
sensorEditComponentRef.instance.sensorId = id;
}
The actual dynamic component is very simple, and its registered in the entryComponents section in AppModule.实际的动态组件非常简单,在AppModule的entryComponents部分注册。 I've narrow it down to the bare minimum in order to understand what's wrong:
我已将其缩小到最低限度,以了解出了什么问题:
@Component({
selector: 'app-sensor-edit',
templateUrl: './sensor-edit.component.html',
styleUrls: ['./sensor-edit.component.css']
})
export class SensorEditComponent implements OnInit {
@Input() sensorId: number;
private showDialog: boolean = false;
constructor() {
console.log('constructor');
}
ngOnInit() {
console.log('ngOnInit');
this.showDialog = true;
}
Last, the HTML for the dynamic component:最后,动态组件的 HTML:
<div *ngIf="showDialog">
<h3>its not working</h3>
</div>
The problem is that ngOnInit from the dynamic component doesn't get called and I have the rest of the data to initialize in there, so that I can build the rest of the template.问题是动态组件中的 ngOnInit 没有被调用,我有其余的数据要在那里初始化,以便我可以构建模板的其余部分。
The really weird part is that if my console is not opened, and I open it or vice-versa, the template is shown.真正奇怪的部分是,如果我的控制台没有打开,而我打开它,反之亦然,则会显示模板。
Based on the answers in comment by @codingandstuff above, just want to make it more clear with code changes for the example above.根据上面@codingandstuff 在评论中的回答,只是想通过上面示例的代码更改使其更加清晰。
Also, I would like this answer to be here as a reference for anybody who googles "how to generate / inject / render dynamic component in angular".另外,我希望这个答案在这里作为任何在谷歌上搜索“如何以角度生成/注入/渲染动态组件”的参考。
@Directive({
selector: '[appPlaceholder]'
})
export class PlaceholderDirective {
constructor(
public viewContainerRef: ViewContainerRef,
public changeDetectorRef: ChangeDetectorRef,
) {}
}
@ViewChild(PlaceholderDirective, {static: false}) private placeholder: PlaceholderDirective;
...
constructor(private componentResolver: ComponentFactoryResolver) {}
...
public launchSensorEditComponent(id: number) {
const componentFactory = this.componentResolver.resolveComponentFactory(SensorEditComponent);
const hostViewContainerRef = this.placeholder.viewContainerRef;
hostViewContainerRef.clear();
const sensorEditComponentRef = hostViewContainerRef.createComponent(componentFactory);
sensorEditComponentRef.instance.sensorId = id;
this.placeholder.changeDetectorRef.detectChanges(); // <-- this line has been added
}
And if you've upgraded Angular to 13+, then please note that now you can provide component class directly to createComponent without dealing with componentResolver, componentFactory etc. Just like this:如果你已经将 Angular 升级到 13+,那么请注意,现在你可以直接将组件类提供给 createComponent 而不需要处理 componentResolver、componentFactory 等。就像这样:
public launchSensorEditComponent(id: number) {
const { hostViewContainerRef, changeDetectorRef } = this.placeholder;
hostViewContainerRef.clear();
const sensorEditComponentRef = hostViewContainerRef.createComponent(SensorEditComponent);
sensorEditComponentRef.instance.sensorId = id;
changeDetectorRef.detectChanges();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.