Dremor
Dremor

Reputation: 831

Angular : Table with header and subheader

I'm trying to make a table with sub-columns from an array of column object that can itself contain sub-columns.

The header object :

export class ListHeader {
    id: string;
    label: string;
    type: int;
    subColumns?: ListHeader[];
}

Table component partial code

columns: ListHeader[];
columnsWithSubColumns: ListHeader[];

constructor(){
   this.columns = [{
        id: "AC1",
        label: "AC1",
        type: 1
      },
      {
        id: "AC3",
        label: "AC3",
        type: 1
      },
      {
        id: "AC2",
        label: "AC2",
        type: 1,
        subColumns: [
          {
            id: "ColB",
            label: "ColB",
            type: 1
          },
          {
            id: "ColA",
            label: "ColA",
            type: 1
          },
          {
            id: "ColC",
            label: "ColC",
            type: 1
          }
        ]
      }
   ];
   this.columnsWithSubColumns = this.columns
            .filter(c => typeof c.subColumns !== 'undefined' && c.subColumns !== null && c.subColumns.length > 1);
}

The HTML :

<table>
    <thead>
        <tr>
            <th *ngFor='let key of columns' [id]='key.id'>
                {{ key.label }}
            </th>
        </tr>
        <tr>
            <th *ngFor='let key of columnsWithSubColumns '>
                <--! Can't figure how to do from there -->
            </th>
        </tr>
    </thead>
  <--! tbody, etc... -->
</table>

I tied multiple solution, by modifying the HTML and/or the underlying Typescript, but I'm unable to find a way to show correctly the sub-columns. Either they shows under the wrong column, or don't shows at all.

I've found a working static table that does wore or less what I want (http://jsfiddle.net/8qycxkv9/), but I'm looking to make it dynamics.

As such, I'm trying to create a second array of ListHeader, from all subHeaders arrays in the columns Array. I managed to filter out the columns without subcolumns, but can't find a way to go further.

I'm open to any implementation, the only constrain is keeping as it the ListHeader object.

Upvotes: 0

Views: 3495

Answers (2)

Stak
Stak

Reputation: 366

try this it is working as you intended.

<table>
  <thead>
      <tr>
          <ng-container *ngFor='let key of columns'>
              <th *ngIf='key.subColumns' [id]='key.id' [attr.colspan]=key.subColumns.length>
                  {{ key.label }}
              </th>
              <th *ngIf='!key.subColumns' [id]='key.id' [attr.rowspan]=2>
                  {{ key.label }}
              </th>
          </ng-container>
      </tr>
      <tr>
          <ng-container *ngFor='let key of columnsWithSubColumns'>
          <th *ngFor="let sub of key.subColumns">
            {{sub.label}}
          </th>
          </ng-container>
      </tr>
  </thead>
</table>

Upvotes: 1

Silird
Silird

Reputation: 186

You need to use attribute "colspan" in first array, which mean how many subheaders will be under this header.

You get something like this:

<table>
    <thead>
        <tr>
            <th *ngFor='let key of columns' [id]='key.id' colspan=key.subColumns.length>
                {{ key.label }}
            </th>
        </tr>
        <tr>
            <ng-container *ngFor='let key of columns'>
                <th *ngFor='let subheader of key.subColumns'>
                    {{subheader.label}}
                </th>
            </ng-container>
        </tr>
    </thead>
  <--! tbody, etc... -->
</table>

If some of your columns don't have subtitles you can do something like this:

<table>
    <thead>
        <tr>
            <ng-container *ngFor='let key of columns'>
                <th *ngIf='key.subColumns' [id]='key.id' [attr.colspan]=key.subColumns.length>
                    {{ key.label }}
                </th>
                <th *ngIf='!key.subColumns' [id]='key.id' [attr.rowspan]=2>
                    {{ key.label }}
                </th>
            </ng-container>
        </tr>
        <tr>
            <ng-container *ngFor='let key of columns'>
                <th *ngFor='let subheader of key.subColumns'>
                    {{subheader.label}}
                </th>
            </ng-container>
        </tr>
    </thead>
  <--! tbody, etc... -->
</table>

Then columns with subtitles would be wide, and columns without it would be tall.

Upvotes: 2

Related Questions