'Why does matColumnDef not need the asterisk notation in mat-table?

I was curious why *matCellDef, *matHeaderCellDef, and *matRowDef are all using structural/asterisk notation but the matColumnDef is not? Is it because the former are using some template container and matColumnDef basically just gets/sets the class name? Could you give an explanation with an example?



Solution 1:[1]

This is my understanding of the matter.

The asterisk (*) is a convenience notation and the string is a microsyntax rather than the usual template expression. Angular desugars this notation into a marked-up <ng-template> that surrounds the host element and its descendants. Each structural directive does something different with that template. https://angular.io/guide/structural-directives

When writing HTML source code, you can define attributes on your HTML elements. Then, once the browser parses your code, a corresponding DOM node will be created. This node is an object, and therefore it has properties.

For instance, this HTML element will define for inner workings of Table component, that this node will be column and associates it with name. When rendering rest of the table happens, we know where to put children nodes that are name elements and belong in there.

So now when *matHeaderCellDef is rendering and changing stuff in DOM, we know that matching name cells/rows should go into matColumnDef="name".

<ng-container matColumnDef="name">

To sum it up * manipulates and changes nodes in the DOM whilst attributes are there to define what they are, but not change anything.

Solution 2:[2]

Asterisk *, is a syntactic sugar in Angular From angular documentation:

The asterisk, *, syntax on a structural directive, such as *ngIf, is shorthand that Angular interprets into a longer form. Angular transforms the asterisk in front of a structural directive into an that surrounds the host element and its descendants.

   <div *ngIf="hero" class="name">{{hero.name}}</div>

is the same as

   <ng-template [ngIf]="hero">
     <div class="name">{{hero.name}}</div>
   </ng-template>

The matColumnDef directive is used to uniquely identify a given column with a key Hence it's applied on an ng-container which is not rendered on the screen, but we needed a container/template so that we could apply our matColumnDef directive. which defines the set of cells available for a table column. Which tells the DOM that this is table cell with the name

If mat matColumnDef had an asterisk with it i.e. it was a structural directive. Angular would interpret it into a longer form which would look like:

<ng-container [matColumnDef]="testing">
    <ng-template>
      <ng-container>
          Rest of HTML
      </ng-container>
    </ng-template>

Normal material table cell definition:

<ng-container matColumnDef="testing">
  <mat-header-cell *matHeaderCellDef></mat-header-cell>
  <mat-cell *matCellDef="let element" class="pl-3">
    <div>
      <img class="device-icon" src="assets/fresh_air2b.png" alt="">
    </div>
  </mat-cell>
</ng-container>

Angular's longer form material table cell definition would look like this:

<ng-container matColumnDef="testing">
  <!-- Not sure what is binded matHeaderRowDef  -->
  <ng-template [matHeaderCellDef]>
    <mat-header-cell ></mat-header-cell>
  </ng-template>
  <ng-template [matCellDef]="element">
    <mat-cell></mat-cell>
  </ng-template>
</ng-container>

The only confusion remains for me atleast is why is there no binding explicitly for *matHeaderCellDef, is it done implicitly?

For reference: https://angular.io/guide/structural-directives#structural-directive-shorthand

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2