Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/29.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 在*ngIf-createComponent中加载动态组件未定义_Angular_Angular8_Angular Ng If - Fatal编程技术网

Angular 在*ngIf-createComponent中加载动态组件未定义

Angular 在*ngIf-createComponent中加载动态组件未定义,angular,angular8,angular-ng-if,Angular,Angular8,Angular Ng If,当用户单击按钮时,我试图将动态组件加载到我的视图中,该按钮如下所示: <button (click)="showContent()">Show Panel</button> <!--This starts as 'showPanel = false'--> <div *ngIf="showPanel"> <ng-template #ref></ng-template> </div> 这是因为*ngIf在

当用户单击按钮时,我试图将动态组件加载到我的视图中,该按钮如下所示:

<button (click)="showContent()">Show Panel</button>
<!--This starts as 'showPanel = false'-->
<div *ngIf="showPanel">
    <ng-template #ref></ng-template>
</div>

这是因为*ngIf在条件计算为false时删除div元素,这意味着子元素不存在于组件模板中

您可以改为使用[hidden],它只隐藏div元素,以便您可以通过模板引用变量访问它

<button (click)="showContent()">Show Panel</button>
<!--This starts as 'showPanel = false'-->
<div [hidden]="!showPanel">
    <ng-template #ref></ng-template>
</div>
显示面板

继yurzui的想法之后,我将如何应用这些想法:

这是一个闪电战的例子

changeDetectorRef.detectChanges()
showContent(){
this.showPanel=!this.showPanel;
如果(此.showPanel){
this.cdr.detectChanges();
这个.loadComponent();
}
}
ViewChild的setter
private\u ref:ViewContainerRef;
私有get ref(){
将此返回。\u ref;
}
@ViewChild('ref',{static:false,read:ViewContainerRef})
专用集参考(r){
console.log('settingref',r)
这个._ref=r;
如果(本参考){
这个.loadComponent();
}
}
showPanel=false;
建造师(
私人cdr:ChangeDetectorRef,
专用cfr:ComponentFactoryResolver,
) { }
loadComponent(){
常量工厂=此.cfr.resolveComponentFactory(ChildComponent);
常量组件=此.ref.createComponent(工厂);
}
showContent(){
this.showPanel=!this.showPanel;
}
使用
正如您所指出的,使用
ngTemplateOutlet
通常是一个很好的解决方案,但是当您处理多个组件时,在模板中执行所有这些逻辑可能会变得很麻烦

我们可以利用API处理组件(
.ts文件
)中的所有内容

显示面板
@ViewChild('vcr',{static:true,read:ViewContainerRef})
录像机:ViewContainerRef;
showContent(){
this.showPanel=!this.showPanel;
this.showPanel&&this.attachComponent();
!this.showPanel&&this.removeComponent();
}
私有附件组件(){
const compFactory=此.cfr.resolveComponentFactory(ChildComponent);
const compView=this.vcr.createComponent(compFactory);
}
私有removeComponent(){
这个.vcr.clear();
}
这种方法给你的控制比你能处理的更多
例如,您可以使用
vcr.detach
vcr.insert
在组件
showPanel
变为false后保留其状态


.

我不明白您想如何将组件加载到ref中,因为ref还不存在,因为
showPanel=false
您的DOM元素不存在,因为您在showPanel上以
false
开头,因为您的ref不存在。@yurzui,我理解,但是当您单击按钮并运行loadContent()时,它会失败,并出现同样的错误。在我的问题中,我没有说得很清楚。更新。@米开朗基罗与上面的Yurzui一样,我的问题不是很清楚。我已经更新了它,以显示在您更改showPanel属性时实际发生的情况,但不更新视图。这里有许多选项可供使用:1)使用setter for ViewChild 2)使用ngComponentOutlet渲染组件3)在
this.showPanel=之后使用cdRef.detectChanges()!这个.showPanel如果不必加载组件,我宁愿不加载组件。拥有[隐藏]仍然意味着我必须在使用组件之前渲染它。不太理想。但我没有说过需要在ngAfterViewInit()方法中加载组件,您的代码提到这行有注释。我的问题写得很糟糕,我的问题是在ngAfterViewInit生命周期挂钩之后加载组件。尝试运行loadComponent()时抛出错误,声明在*ngIf设置为true后无法读取未定义的属性“createComponent”。这样做的目的是不将任何不必存在的内容加载到DOM中,因为它不会显示任何内容,直到用户单击Show Panel按钮后将其替换为动态组件。因此,我从div中删除了ng模板,它实际上在button click上工作,但是我需要利用div样式类。如果*ngIf=true,什么会阻止组件加载?这是因为它的状态在变化吗?哇,确实有很多选择!我最终接受了这个建议。
<button (click)="showContent()">Show Panel</button>
<!--This starts as 'showPanel = false'-->
<div [hidden]="!showPanel">
    <ng-template #ref></ng-template>
</div>