Динамічний компонент всередині ngx-даних, що може бути деталізований рядок


9

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


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помилку на методі компонентFactory.create. Будь-яка ідея, чому це може статися? this.dynamicPlaceholder.elementRef.nativeElement повертає коментар, може це бути?
Рагхав Канваль

@RaghavKanwal дивіться мою оновлену відповідь.
Ельдар
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.