AngularのCDK Tableのコードを読みながら、Viewの組み立て方について調べる

段階的に実装してみたサンプルコードを晒します。完成版とおまけを除くと8ステップにわかれています。

Viewの組み立て部分を参考にしたかったので、DataSourceやIterableDiffers, TrackByFunctionなどを利用したコードはありません。

CDK Tableのドキュメント

0: 完成版

f:id:ryotah:20180124234812p:plain

1: コンポーネントを動的にaddする

2: 対象のコンポーネント内にaddする

3: コンポーネントのaddからテンプレートを取得してaddする方式に変更

f:id:ryotah:20180124232835p:plain

4: table.ts, row.ts, cell.tsを用意

  • angular-cdk-datatable-04-celldefs - StackBlitz
    • 各セルの内容を定義するために、CellDefという考え方を導入
    • この段階では実態は export class CellDef { constructor(public template: TemplateRef<any>) {} } というDirective

5: 行定義を追加(RowDef)

app.component.html

<my-table [data]="data">
    <!-- cellを定義 -->
    <ng-container *cellDef="let data;">
        <span style="border: 1px solid cyan;">[cell-1] {{data}}</span>
    </ng-container>
    <ng-container *cellDef="let data;">
        <span style="border: 1px solid yello;">[cell-2] {{data}}</span>
    </ng-container>
    <ng-container *cellDef="let data;">
        <span style="border: 1px solid blue;">[cell-3] {{data}}</span>
    </ng-container>
  
</my-table>  

table.html

<!-- rowを定義 -->
<ng-container *rowDef>
    <div style="border: 1px solid red; background-color: rgba(255,0,0,.2)">[row]
        <ng-container cellOutlet></ng-container>
    </div>
</ng-container>

6: ヘッダー用の行定義を追加(HeaderRowDef)

f:id:ryotah:20180124234656p:plain

app.component.html

<my-table [columns]="columns" [data]="data">

  <!-- header cellを定義 -->
    <ng-container *headerCellDef="let data;">
        <span style="border: 1px solid cyan;">[ttl-1]{{data.title}}</span>
    </ng-container>
    <ng-container *headerCellDef="let data;">
        <span style="border: 1px solid green;">[ttl-2]{{data.title}}</span>
    </ng-container>
    <ng-container *headerCellDef="let data;">
        <span style="border: 1px solid blue;">[ttl-2]{{data.title}}</span>
    </ng-container>

    <!-- cellを定義 -->
    <ng-container *cellDef="let data;">
        <span style="border: 1px solid cyan;">[cell-1] {{data}}</span>
    </ng-container>
    <ng-container *cellDef="let data;">
        <span style="border: 1px solid green;">[cell-2] {{data}}</span>
    </ng-container>
    <ng-container *cellDef="let data;">
        <span style="border: 1px solid blue;">[cell-3] {{data}}</span>
    </ng-container>
  
</my-table>  

table.html

<!-- header rowを定義 -->
<ng-container *headerRowDef>
    <div style="border: 1px solid magenta; background-color: rgba(255,0,255,.2)">[row]
        <ng-container cellOutlet></ng-container>
    </div>
</ng-container>

<!-- rowを定義 -->
<ng-container *rowDef>
    <div style="border: 1px solid red; background-color: rgba(255,0,0,.2)">[row]
        <ng-container cellOutlet></ng-container>
    </div>
</ng-container>

7: accessorを追加

8: header cell, cellの定義をcolumnの定義でまとめる

f:id:ryotah:20180124235744p:plain

app.component.html

<my-table [data]="data">

    <!-- [name] columnを定義 -->
    <ng-container columnDef="name">
        <ng-container *headerCellDef>
            <span style="border: 1px solid cyan;">Name</span>
        </ng-container>
        <ng-container *cellDef="let row;">
            <span style="border: 1px solid cyan;">{{row.name}}</span>
        </ng-container>
    </ng-container>
    <!-- [age] columnを定義 -->
    <ng-container columnDef="age">
        <ng-container *headerCellDef>
            <span style="border: 1px solid green;">Age</span>
        </ng-container>
        <ng-container *cellDef="let row;">
            <span style="border: 1px solid green;">{{row.age}}</span>
        </ng-container>
    </ng-container>
    <!-- [id] columnを定義 -->
    <ng-container columnDef="id">
        <ng-container *headerCellDef>
            <span style="border: 1px solid blue;">Id</span>
        </ng-container>
        <ng-container *cellDef="let row;">
            <span style="border: 1px solid blue;">{{row.id}}</span>
        </ng-container>
    </ng-container>

</my-table>

9: おまけ