skip to Main Content

I have data like this:

const parents = [
    {
        name: "Bob",
        children: [
            {
                name: "Mike"
            },
            {
                name: "Sarah"
            }
        ]
    },
    {
        name: "Jim",
        children: [
            {
                name: "Eve"
            },
            {
                name: "Kenny"
            },
            {
                name: "Brook"
            }
        ]
    }
]

I’m trying to create a table that displays the nested children as rows, and would like to use mat-table to match the styling of the rest of my app.

So it should look like this:

Child Name    |Parent Name
---------------------------
Mike          |Bob
---------------------------
Sarah         |Bob
---------------------------
Eve           |Jim
---------------------------
Kenny         |Jim
---------------------------
Brook         |Jim
---------------------------

I also want columns to include both child and parent names. Currently, I have:

<mat-table
  [dataSource]="parents"
>
  <ng-container matColumnDef="childName">
    <mat-header-cell *matHeaderCellDef>Child Name</mat-header-cell>
  </ng-container>

  <ng-container matColumnDef="parentName">
    <mat-header-cell *matHeaderCellDef>Parent Name</mat-header-cell>
  </ng-container>

  <ng-container matColumnDef="parents">
    <td mat-cell *matCellDef="let parent" [attr.colspan]="displayedColumns.length">
      <tr *ngFor="let child of parent.children">
        {{ child.name }}
      </tr>
    </td>
  </ng-container>

  <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
  <tr mat-row *matRowDef="let row; columns: ['parents']"></tr>
</mat-table>

But I’m getting stuck on how to get the cells to line up with the headers.

2

Answers


  1. Does this work?

    <mat-table [dataSource]="parents">
      <!-- headers -->
      <ng-container matColumnDef="parentName">
        <mat-header-cell *matHeaderCellDef>Parent Name</mat-header-cell>
        <mat-cell *matCellDef="let parent">{{ parent.name }}</mat-cell>
      </ng-container>
    
      <ng-container matColumnDef="childName">
        <mat-header-cell *matHeaderCellDef>Child Name</mat-header-cell>
        <mat-cell *matCellDef="let parent">
          <ng-container *ngFor="let child of parent.children">
            <tr>
              <td>{{ child.name }}</td>
              <td>{{ parent.name }}</td>
            </tr>
          </ng-container>
        </mat-cell>
      </ng-container>
    
      <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
      <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
    </mat-table>
    
    Login or Signup to reply.
  2. You can create a dataSource based in your data received

      const data = parents.reduce((a: any, b: any) => {
        b.children.forEach((x: any) => {
          a.push({ child: x.name, parent: b.name });
        });
        return a;
      }, []);
    

    reduce loop over all the elements of the array, Each element is get in the variable "b", and "a" is the "acumulator", that can be an initial value (in this case an empty array)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search