Componente dinamico all'interno del dettaglio riga ngx-datatable


9

Sto creando un datatable riutilizzabile usando ngx-datatable e vorrei avere componenti dinamici resi nei dettagli della riga. Il componente datatable riceve una classe di componente come argomento da un modulo padre e io uso ComponentFactory per creareComponent. Vedo che il costruttore e i metodi onInit sono in esecuzione per il componente dinamico ma non è collegato al DOM.

Ecco come appare l'html datatable per il dettaglio riga:

 <!-- [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] -->

E questo è come appare il mio file .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);
}

Un altro punto è che se il mio #dynamicPlaceholderng-template viene posizionato al di fuori di ngx-datatable, funziona e il modulo dinamico viene visualizzato e visualizzato.


1
Questo ha a che fare con la proiezione dei contenuti. Tutto ciò che viene inserito tra un tag componente non viene visualizzato a meno che il componente non abbia un <ng-content>tag per eseguire il rendering di qualsiasi markup nidificato.
C_Ogoo

Potresti per favore aiutarmi con un rapido esempio per aiutare nel mio caso?
Raghav Kanwal,

Risposte:


2

Non è possibile eseguire il rendering di un componente in un Template ( <ng-template>) in fase di esecuzione createComponent
poiché i modelli afaik vengono elaborati da Angular al momento della compilazione. Quindi abbiamo bisogno di una soluzione che funzioni in fase di compilazione.


Soluzione con inconvenienti

ng-content può aiutarci qui:

<!-- [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] -->

Possiamo quindi passare tutto ciò che vogliamo alla vista di dettaglio:

<my-table>From the ouside but I cant access the current row :(</my-table>

Ma c'è un problema: non possiamo usare ng-contentquando vogliamo accedere alla riga corrente nel modello passato.


Soluzione

Ma ngx-datatableci ha coperto. Possiamo passare un modello alla ngx-datatable-row-detaildirettiva:

<ngx-datatable-row-detail [template]="myDetailTemplate "rowHeight="100" (toggle)="onDetailToggle($event)">
</ngx-datatable-row-detail>

Il modello può quindi essere passato da qualsiasi componente esterno tramite una @Inputvariabile:

<ng-template #myDetailTemplate let-row="row">
  From the outside with access to the current row: {{row.name}}
</ng-template>

Dai un'occhiata allo stackblitz , dove ho scritto un my-tablecomponente come poc.


0

Definire un componente che espone il suo contenuto come 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>

Utilizzare ViewChildper rendere una proprietà accessibile perTemplateRef

export class DynamicComponent implements OnInit {

  @ViewChild("myTemplate",{static:true}) myTempalte : TemplateRef<any>
...
}

Definisci i dettagli della riga senza modello

<ngx-datatable-row-detail rowHeight="100" (toggle)="onDetailToggle($event)">
</ngx-datatable-row-detail>

Definire una proprietà per accedere alla direttiva

@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

Modifica: ho armeggiato con la ngx-datatableparte triste di origine non ngx-datatable-row-detailè un componente ma direttiva e non è collegato a DOM. Quindi non ha alcun riferimento ViewContainer. Questo rende l'iniezione di elementi in esso un po 'difficile. Quello che puoi fare è definire modelli nel tuo componente e usare TemplateRefs e assegnarli dove renderizzi il tuo componente.


Grazie per l'input, ho provato ad adottare il tuo metodo ma sto ricevendo un el.setAttribute is not a functionerrore sul metodo componentFactory.create. Qualche idea sul perché ciò possa accadere? this.dynamicPlaceholder.elementRef.nativeElement restituisce un commento, potrebbe essere?
Raghav Kanwal,

@RaghavKanwal vedi la mia risposta aggiornata.
Eldar
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.