Динамический компонент внутри ngx-datatable row-detail

9

Я создаю повторно используемую таблицу данных, используя ngx-datatable, и я хотел бы, чтобы динамические компоненты отображались внутри детали строки. Компонент datatable получает класс компонента в качестве аргумента от родительского модуля, и я использую ComponentFactory для createComponent. Я вижу, что конструктор и методы 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);
}

Другой момент заключается в том, что если мой #dynamicPlaceholderng-шаблон находится вне ngx-datatable, он работает, и динамический модуль отображается и отображается.

Рагхав Канвал
источник
1
Это связано с проекцией контента. Все, что находится между тегом компонента, не отображается, если компонент не имеет <ng-content>тега для отображения любой вложенной разметки.
C_Ogoo
Не могли бы вы помочь мне с быстрым примером, чтобы помочь в моем случае?
Рагхав Канвал

Ответы:

2

Мы не можем отобразить компонент в Template ( <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.

Криси
источник
0

Определите компонент, который предоставляет его содержимое как 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);
}

Stackblitz

Изменить: я возился с ngx-datatableисточником печальная часть этого ngx-datatable-row-detailне является компонентом, но директива, и он не привязан к DOM. Так что это не имеет ViewContainerссылки. Это делает введение элементов в него немного сложным. Что вы можете сделать, это определить шаблоны в вашем компоненте и использовать TemplateRefs и назначить их в том месте, где вы визуализируете свой компонент.

Эльдар
источник
Спасибо за ввод, я попытался принять ваш метод, но я получаю el.setAttribute is not a functionошибку в методе componentFactory.create. Есть идеи, почему это может происходить? this.dynamicPlaceholder.elementRef.nativeElement возвращает комментарий, не так ли?
Рагхав Канвал
@RaghavKanwal посмотрите мой обновленный ответ.
Эльдар