定义一个将其内容公开为
TemplateRef
的组件
我正在使用ngx-datatable创建可重用的数据表,我希望在行详细信息内呈现动态组件。数据表组件从父模块接收一个组件类作为参数,我使用ComponentFactory来创建组件。我可以看到该构造函数和onInit方法正在为动态组件运行,但没有附加到DOM。
这是数据表html的行详细信息:
<!-- [Row Detail Template] -->
<ngx-datatable-row-detail rowHeight="100" #myDetailRow (toggle)="onDetailToggle($event)">
<ng-template let-row="row" #dynamicPlaceholder let-expanded="expanded" ngx-datatable-row-detail-template>
</ng-template>
</ngx-datatable-row-detail>
<!-- [/Row Detail Template] -->
这就是我的.ts文件的样子:
@ViewChild('myDetailRow', {static: true, read: ViewContainerRef}) myDetailRow: ViewContainerRef;
@ViewChild('dynamicPlaceholder', {static: true, read: ViewContainerRef}) dynamicPlaceholder: ViewContainerRef;
renderDynamicComponent(component) {
var componentFactory = this.componentFactoryResolver.resolveComponentFactory(component);
var hostViewConRef1 = this.myDetailRow;
var hostViewConRef2 = this.dynamicPlaceholder;
hostViewConRef1.createComponent(componentFactory);
hostViewConRef2.createComponent(componentFactory);
}
另一点是,如果将我的#dynamicPlaceholder
ng-template放置在ngx-datatable的外部,则它可以工作,并且呈现并显示动态模块。
我们无法在运行时使用<ng-template>
将组件渲染到模板(createComponent
)中因为afaik模板会在编译时由Angular处理。因此,我们需要一个在编译时有效的解决方案。
有缺点的解决方案>>
ng-content
可以在这里帮助我们:
<!-- [Row Detail Template] --> <ngx-datatable-row-detail rowHeight="100" (toggle)="onDetailToggle($event)"> <ng-template let-row="row" let-expanded="expanded" ngx-datatable-row-detail-template> <ng-content></ng-content> </ng-template> </ngx-datatable-row-detail> <!-- [/Row Detail Template] -->
然后我们可以将所需的任何内容传递给详细视图:
当我们想访问传递的模板中的当前行时,不能使用<my-table>From the ouside but I cant access the current row :(</my-table>
但是有一个问题:
ng-content
。解决方案>>
但是ngx-datatable
让我们蒙上了一层阴影。我们可以将模板传递给ngx-datatable-row-detail
指令:
<ngx-datatable-row-detail [template]="myDetailTemplate "rowHeight="100" (toggle)="onDetailToggle($event)"> </ngx-datatable-row-detail>
然后可以通过
@Input
变量从外部的任何组件传递模板:<ng-template #myDetailTemplate let-row="row"> From the outside with access to the current row: {{row.name}} </ng-template>
[看一下stackblitz,我在其中写了一个
my-table
组件为poc。
定义一个将其内容公开为
TemplateRef
的组件
<ng-template #myTemplate let-row="row" let-expanded="expanded" ngx-datatable-row-detail-template> <div><strong>Address</strong></div> <div>{{ row?.address?.city }}, {{ row?.address?.state }}</div> </ng-template>
使用
ViewChild
为TemplateRef
设置可访问属性
export class DynamicComponent implements OnInit { @ViewChild("myTemplate",{static:true}) myTempalte : TemplateRef<any> ... }
定义没有模板的行详细信息
<ngx-datatable-row-detail rowHeight="100" (toggle)="onDetailToggle($event)"> </ngx-datatable-row-detail>
定义属性以访问指令
我摆弄了@ViewChild(DatatableRowDetailDirective,{static:true}) templ:DatatableRowDetailDirective; constructor( private cfr: ComponentFactoryResolver, //import cfr ) .... toggleExpandRow(row) { const factory = this.cfr.resolveComponentFactory<DynamicComponent>( DynamicComponent ); const component = factory.create(this.injector,[]); //create component dynamically this.templ._templateInput = component.instance.myTempalte; // set directives template to your components template this.table.rowDetail.toggleExpandRow(row); }
Edit:
ngx-datatable
源代码,可悲的是ngx-datatable-row-detail
不是组件,而是指令,并且未附加到DOM。因此,它没有ViewContainer
参考。这使得向其中注入元素有些困难。您可以做的是在组件中定义模板,并使用TemplateRef
并将其分配给渲染组件的位置。 定义一个将其内容公开为
TemplateRef
的组件