Komponen Dinamis di dalam detail baris ngx-datatable

9

Saya membuat datatable dapat digunakan kembali menggunakan ngx-datatable dan saya ingin memiliki komponen dinamis yang dirender di dalam detail baris. Komponen datatable menerima kelas komponen sebagai argumen dari modul induk dan saya menggunakan ComponentFactory untuk membuatComponent. Saya dapat melihat bahwa konstruktor dan metode onInit berjalan untuk komponen dinamis tetapi tidak dilampirkan ke DOM.

Inilah tampilan dari html yang dapat datatable untuk detail baris:

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

Dan inilah tampilan file .ts saya:

@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);
}

Poin lain adalah bahwa jika #dynamicPlaceholdertemplate-ng saya ditempatkan di luar ngx-datatable, ia berfungsi dan modul dinamis di-render dan ditampilkan.

Raghav Kanwal
sumber
1
Ini berkaitan dengan proyeksi konten. Apa pun yang ditempatkan di antara tag komponen, tidak diberikan kecuali komponen memiliki <ng-content>tag untuk memberikan markup bersarang.
C_Ogoo
Bisakah Anda membantu saya dengan contoh cepat untuk membantu dalam kasus saya?
Raghav Kanwal

Jawaban:

2

Kami tidak dapat merender komponen menjadi Templat ( <ng-template>) saat runtime dengan createComponent
karena templat afaik diproses oleh Angular pada waktu kompilasi. Jadi kita membutuhkan solusi yang berfungsi pada waktu kompilasi.


Solusi dengan kekurangan

ng-content dapat membantu kami di sini:

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

Kami kemudian dapat melewatkan apa pun yang kami inginkan ke tampilan detail:

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

Tetapi ada masalah: Kita tidak bisa menggunakan ng-contentketika kita ingin mengakses baris saat ini di templat yang diteruskan.


Larutan

Tetapi ngx-datatablemembuat kami terlindungi. Kami dapat mengirimkan templat ke ngx-datatable-row-detailarahan:

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

Template kemudian dapat ditularkan dari komponen di luar melalui @Inputvariabel:

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

Lihatlah stackblitz , di mana saya menulis my-tablekomponen sebagai poc.

ChrisY
sumber
0

Tentukan komponen yang memperlihatkan kontennya sebagai 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>

Gunakan ViewChilduntuk membuat properti yang dapat diaksesTemplateRef

export class DynamicComponent implements OnInit {

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

Tentukan detail baris Anda tanpa template

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

Tetapkan properti untuk mengakses arahan

@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

Sunting: Saya mengutak-atik ngx-datatablebagian sumber sedih itu ngx-datatable-row-detailbukan komponen tetapi arahan dan tidak melekat pada DOM. Jadi tidak ada ViewContainerreferensi. Ini membuat elemen injeksi menjadi sedikit sulit. Yang dapat Anda lakukan adalah mendefinisikan templat di komponen Anda dan menggunakan TemplateRefs dan menugaskan mereka di mana Anda membuat komponen Anda.

Eldar
sumber
Terima kasih atas masukannya, saya mencoba mengadopsi metode Anda, tetapi saya mendapatkan el.setAttribute is not a functionkesalahan pada metode componentFactory.create. Adakah yang tahu mengapa itu bisa terjadi? this.dynamicPlaceholder.elementRef.nativeElement mengembalikan komentar, mungkinkah itu?
Raghav Kanwal
@RaghavKanwal lihat jawaban saya yang diperbarui.
Eldar