Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular material 2 table - define column using TemplateRef and ngTemplateOutlet

I am trying to make reusable material table and I want to use TemplateRef with ngTemplateOutlet to generate columns. In this example I created cards components which is using my material-table component. In cards.component.html I have template of one of my table's column. Running the project will cause an error ERROR TypeError: Cannot read property 'template' of undefined (see console on stackblitz). Is it possible to pass columnt template to my MaterialTableComponent and use it to define column?

 <table mat-table [dataSource]="data" class="mat-elevation-z4">
  <ng-container
    *ngFor="let column of displayedColumnObjects"
    [matColumnDef]="column.id"
  >
  <!-- if where is cellTemplate in table config json, use cellTemplate  -->
    <ng-container
      *ngIf="column.cellTemplate" 
      [ngTemplateOutlet]="column.cellTemplate"
    >
    </ng-container>

    <ng-container *ngIf="!column.cellTemplate">
      <th mat-header-cell *matHeaderCellDef> {{column.title}} </th>
      <td mat-cell *matCellDef="let element"> {{element[column.id]}} </td>
    </ng-container>

  </ng-container>

  <tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
  <tr mat-row *matRowDef="let row; columns: columnsToDisplay;"></tr>
</table>

UPDATE I found solution using ngTemplateOutletContext.

<table mat-table [dataSource]="data" class="mat-elevation-z4">
  <ng-container
    *ngFor="let column of displayedColumnObjects"
    [matColumnDef]="column.id"
  >

    <ng-container
      *ngIf="column.cellTemplate"
    >
      <th mat-header-cell *matHeaderCellDef> {{column.title}} </th>
      <td mat-cell *matCellDef="let element"> 
        <ng-template
          [ngTemplateOutletContext]="{
            element: element[column.id]
          }"
          [ngTemplateOutlet]="column.cellTemplate">
        </ng-template>
      </td>
    </ng-container>

    <ng-container *ngIf="!column.cellTemplate">
      <th mat-header-cell *matHeaderCellDef> {{column.title}} </th>
      <td mat-cell *matCellDef="let element"> {{element[column.id]}} </td>
    </ng-container>

  </ng-container>

  <tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
  <tr mat-row *matRowDef="let row; columns: columnsToDisplay;"></tr>
</table>

See my example

like image 583
tprieboj Avatar asked Oct 15 '18 08:10

tprieboj


1 Answers

ADD THE FOLLOWING IN THE COMPONENT TO BE RE-USED

In the '.HTML' file:

<ng-container [ngTemplateOutlet] = "yourNameReference"
[ngTemplateOutletContext] = "{$ implicit: {name: 'Arthur', lastName: 'Lemos'}">
</ng-container>
  • [NgTemplateOutletContext] data will be sent to the parent component. Remembering that '$ implicit' can receive any data you want to send to the PAI component

In the '.ts' file OF THE REUSABLE COMPONENT add the following code WITHIN YOUR CLASS

@ContentChild ('yourNameReference') yourNameReference: TemplateRef <any>;

FATHER COMPONENT (RECEIVES THE RE-USED COMPONENT)

Add the following code to the '.html' file

<ng-template #yourNameReference let-myDataa>
<p> {{myDataa.name}} {{myDataa.lastName}} </p>
</ng-template>


That way you can send data from the child component to the parent component, so you can create dynamic columns for your table.

Just follow the steps above, however, applying the specific columns of the table ... EX:

  <td> <ng-container [ngTemplateOutlet] = "yourNameReference"
[ngTemplateOutletContext] = "{$ implicit: {name: 'Arthur', lastName: 'Lemos'}">
</ng-container> </td>

Add to the child's .ts:

@ContentChild ('yourNameReference') yourNameReference: TemplateRef <any>;

In the parent component:

<my-table>
...
<ng-template #yourNameReference let-myDataa>
<p> {{myDataa.name}} {{myDataa.lastName}} </p>
</ng-template>
<! - this content will be rendered inside the table ... ->
...
</my-table>

YOU CAN CREATE A REFERENCE NAME FOR EACH COLUMN, AND REPEAT THE PROCESS


ANGLE VERSION: 9 DOCUMENTATION: https://angular.io/api/common/NgTemplateOutlet

  • The documentation does not show the use of ngTemplateOutlet in different components, but it already helps in something.
like image 104
Arthur Cabral Avatar answered Nov 17 '22 02:11

Arthur Cabral