我正在使用Angular 5和ng-bootstrap来创建模态模板 demonstrated here
我决定创建一个组件作为模态的模板,并将其命名为 ModalComponent ,以动态创建它并从父组件传递内容给它:
constructor(private modalService: NgbModal){}
onOpenModal(){
this.modalService.open(ModalComponent);
}
我设法触发了通过父组件打开的模式,而且我了解如何将变量传递给模式组件,就像seen in this question+answer一样。
但是,我想将一些HTML内容作为变量传递给ModalComponent,然后将其输出到模板中。本质上,我想实现类似于<app-my-component> some html </app-my-component>
注入'some-html'
到子组件的<ng-content></ng-content>
中的功能。
我敢肯定有一个简单的方法可以对动态创建的组件进行操作,但是我在确定如何做到这一点上遇到了麻烦,而且我了解DOM操作应谨慎进行,最好是使用renderer2。
答案 0 :(得分:2)
您始终可以为模态组件输入'TemplateRef'元素。
如果尚未将ViewChild,ViewContainerRef和TemplateRef导入到模式组件中
import { ..., Input, ViewChild, TemplateRef, ViewContainerRef } from '@angular/core'
在模态组件中,可以在模板中的某个位置创建一个“ anchor”元素,以在其中注入模板输入(或仅将#'d模板变量名称添加到现有元素中)
<div #anchorElement></div>
现在在组件中,声明您的新输入和anchorElement的ViewChild对象
@Input() inputTemplate : TemplateRef<any>;
@ViewChild('anchorElement', {read:ViewContainerRef}) anchor : ViewContainerRef;
现在,您可以在父组件中创建一个ng-template元素,为其指定一个模板变量名称,以便您可以对其进行引用,并将其作为inputTemplate输入发送给模式组件
<ng-template #myTemplate> ...whatever HTML here... </ng-template>
<modal-component [inputTemplate]="myTemplate"></modal-component>
现在,您正在发送该ng-template元素内的任何内容作为模态组件的输入。要实际渲染模板,您需要等到ngAfterViewInit生命周期钩子,然后使用ViewContainerRef的“创建嵌入式视图”方法来注入模板。
在模式组件中:
ngAfterViewInit() {
this.anchor.createEmbeddedView(this.inputTemplate);
}
如果您需要将其切换或删除,则可以调用viewContainerRef的'remove'方法
this.anchor.remove()
此方法的缺点(如果您这样想)是仅限于注入由Angular编译器处理过的模板HTML,因此您不能提取任意外部HTML文件并将其作为使用此方法的模板(除非将它们拉入后手动对它们使用角度编译器,但这很复杂)。您的模板必须在应用程序中的 somewhere 中,以便Angular可以对其进行编译。但是,它们在您的应用程序中有很大的位置自由度。有时,我制作的组件基本上只包含大量不同的ng-template元素,并且给它们一个指令,将它们的TemplateRef上载到单例服务,该单例服务将其存储在地图中。然后,如果我再次在应用程序中需要这些模板,则可以简单地注入该单例服务并从中访问所需的任何模板。只有将Ng-template元素显式地嵌入到视图容器中(否则它们将作为注释处理),才可以呈现Ng-template元素,因此您可以将该主模板组件真正放置在任何地方(我通常将其放置在应用程序的根目录中或附近)以确保其快速可用性)