ngx-datatable 行详细信息中的动态组件
Dynamic Component inside ngx-datatable row-detail
我正在使用 ngx-datatable 创建一个可重复使用的数据表,我希望在行详细信息中呈现动态组件。数据表组件从父模块接收组件 class 作为参数,我使用 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 之外,它就可以工作,动态模块被渲染和显示。
Define a component that exposes its content as 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>
Use ViewChild
to make an accessible property for TemplateRef
export class DynamicComponent implements OnInit {
@ViewChild("myTemplate",{static:true}) myTempalte : TemplateRef<any>
...
}
Define your row detail without template
<ngx-datatable-row-detail rowHeight="100" (toggle)="onDetailToggle($event)">
</ngx-datatable-row-detail>
Define a property to access the directive
@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);
}
编辑: 我摆弄了 ngx-datatable
source sad part of it ngx-datatable-row-detail
不是组件而是指令,它没有附加到 DOM。所以它没有 ViewContainer
参考。这使得向其中注入元素有点困难。您可以做的是在您的组件中定义模板并使用 TemplateRef
s 并将它们分配给您呈现组件的位置。
我们无法在运行时使用 createComponent
将组件渲染到模板 (<ng-template>
) 中
因为 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。
我正在使用 ngx-datatable 创建一个可重复使用的数据表,我希望在行详细信息中呈现动态组件。数据表组件从父模块接收组件 class 作为参数,我使用 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 之外,它就可以工作,动态模块被渲染和显示。
Define a component that exposes its content as
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>
Use
ViewChild
to make an accessible property forTemplateRef
export class DynamicComponent implements OnInit {
@ViewChild("myTemplate",{static:true}) myTempalte : TemplateRef<any>
...
}
Define your row detail without template
<ngx-datatable-row-detail rowHeight="100" (toggle)="onDetailToggle($event)">
</ngx-datatable-row-detail>
Define a property to access the directive
@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);
}
编辑: 我摆弄了 ngx-datatable
source sad part of it ngx-datatable-row-detail
不是组件而是指令,它没有附加到 DOM。所以它没有 ViewContainer
参考。这使得向其中注入元素有点困难。您可以做的是在您的组件中定义模板并使用 TemplateRef
s 并将它们分配给您呈现组件的位置。
我们无法在运行时使用 createComponent
将组件渲染到模板 (<ng-template>
) 中
因为 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。