Home > Software engineering >  How does mat-table's matColumnDef and matCellDef work?
How does mat-table's matColumnDef and matCellDef work?

Time:06-22

I was hoping to build reusable table component from my existing pages with tables. I was naively expecting Angular to have Vuejs like features as scoped slots, slot props. However I could not find any other solution.

Then I came across with the example of mat-table.

I ma wondering could I build such a flexible component to build tables?

CodePudding user response:

The exact directives are *matHeaderCellDef, *matCellDef and matColumnDef.

The last one is only to match the column with the displayed columns. Nothing crazy.

Let's focus on the first two : notice the * before each ?

This is a shortcut to create what is called structural directives.

In angular, you have two type of directives : attributes and structural.

Attributes directives are simple directives that are declared as tag attributes, and modify the behavior of a given element.

Structural directives on the other end, are directives meant to manipulate the DOM tree.

They're used here to inject (or remove) DOM elements into the table, in place of the cells they're declared on.

This is fairly complex and you honestly can find simpler ways of doing so, but if you wish to continue down this path, here is the documentation

CodePudding user response:

I found solution to it. I am new to Angular, and I was reluctant/afraid to use 'complex' built-in components.

Turns out you can use Vuejs scoped slots like feature to create your components.

  1. In table html page you define
<table>
  <tr>
    <th *ngFor="let property of columns | keyvalue">
      <ng-container
         [ngTemplateOutlet]="columnHeader"
         [ngTemplateOutletContext]="{field: property.key, text: property.value}"
      ></ng-container>
    </th>
  </tr>
  <tr *ngFor="let data of datas">
    <td *ngFor="let property of columns | keyvalue">
      <ng-container
         [ngTemplateOutlet]="columnBody"
         [ngTemplateOutletContext]="{$implicit: property.key}"
      ></ng-container>
    </td>
  </tr>
</table>

Here ng-container outputs passed TemplateRef, and pass to that templateRef the data thru ngTemplateOutletContext (either key-value pairs or single value as with $implicit key).

  1. The associated typescript file is:
export class TableComponent implements OnInit {
  @Input() columns!: {[key: string]: string};

  @ContentChild() columnHeader!: TemplateRef<any>;
  @ContentChild() columnBody!: TemplateRef<any>;
}
  1. And the parent compoent can call and pass data as follows;
<app-table
  url="/api/translation/v1/jsons"
  [columns]="{
    col1: 'Column One',
    col2: 'Column Two'
  }"
>
  <ng-template #columnHeader  let-field="field" let-text="text">
    {{field}} {{text}}
  </ng-template>

  <ng-template #columnBody let-field>
    {{field}}
  </ng-template>
</app-table>

This way I could create reusable table component without using libraries

  • Related