skip to Main Content

For context, I need a nested table to group table data (by pdo, program, location). The problem is my th does not aligned with my nested td when the columns are not fully expanded. I’m using Angular 14 and I made sure that my th and td have the same width using [style.width.px]="columnWidths[i]".

When columns not fully expanded, th and td does not aligned
table header
table data

Component.html

<div class="container-parent overflow-auto">
  <table #parentTable class="table-hover table-parent w-100">
    <thead>
      <tr class="th-row">
        <ng-container *ngFor="let header of tableHeaders; let i = index">
          <th
            class="table-headers"
            *ngIf="i < 4"
            [ngClass]="{ 'sticky-left': i < 2 }"
            [style.display]="columns[i].visible ? '' : 'none'"
            [style.width.px]="columnWidths[i]"
          >
            <i
              class="material-icons align-middle"
              [style.cursor]="'pointer'"
              *ngIf="!columns[i + 1]?.visible && i < 3"
              (click)="toggleColumn(i, 'add')"
              >add_box</i
            >
            <i
              class="material-icons align-middle"
              [style.cursor]="'pointer'"
              *ngIf="columns[i + 1]?.visible"
              (click)="toggleColumn(i, 'remove')"
              >indeterminate_check_box</i
            >
            {{ header }}
          </th>
        </ng-container>
        <th class="table-headers" [style.width.px]="columnWidths[4]">
          {{ tableHeaders[4] }}
        </th>
      </tr>
    </thead>
    <tbody>
      <ng-container *ngIf="currentIndex == 0">
        <!-- PDO ROW -->
        <tr class="pdo-row" *ngFor="let pdo of tableData">
          <!-- PDO NAME -->
          <td
            class="td-headers"
            class="pdo-name-column sticky-left"
            [style.width.px]="columnWidths[0]"
            [style.display]="columns[0].visible ? '' : 'none'"
          >
            {{ pdo.name ?? '-' }}
          </td>
          <td class="td-headers" [colSpan]="tableHeaders.length - 1">
            <table class="w-100 h-100">
              <!-- UNIT ITEM ROW -->
              <tr class="unit-item-row">
                <!-- UNIT ITEM -->
                <td
                  class="unit-item-column"
                  [style.width.px]="columnWidths[3]"
                  [style.display]="columns[3].visible ? '' : 'none'"
                >
                  {{ programLocations?.unit_of_item ?? '-' }}
                </td>
                <!-- NO. ITEM -->
                <td class="num-item-column" [style.width.px]="columnWidths[4]">
                  {{ pdo.num_of_items_pdo | number : '1.0-0' ?? '-' }}
                </td>
              </tr>
            </table>
          </td>
        </tr>
      </ng-container>
      <ng-container *ngIf="currentIndex == 1">
        <!-- PDO ROW -->
        <tr class="pdo-row" *ngFor="let pdo of tableData">
          <!-- PDO NAME -->
          <td
            class="td-headers"
            class="pdo-name-column sticky-left"
            [style.width.px]="columnWidths[0]"
            [style.display]="columns[0].visible ? '' : 'none'"
          >
            {{ pdo.name ?? '-' }}
          </td>
          <td class="td-headers" [colSpan]="tableHeaders.length - 1">
            <table class="w-100 h-100">
              <!-- PROGRAM ROW -->
              <ng-container
                *ngFor="
                  let program of pdo.pdo_programs;
                  let programIndex = index
                "
              >
                <tr class="program-row">
                  <!-- PDO PROGRAM -->
                  <td
                    class="pdo-program-column sticky-left"
                    [style.width.px]="columnWidths[1]"
                    [style.display]="columns[1].visible ? '' : 'none'"
                  >
                    {{ program.program ?? '-' }}
                  </td>
                  <td>
                    <table class="w-100 h-100">
                      <!-- UNIT ITEM ROW -->
                      <tr class="unit-item-row">
                        <!-- UNIT ITEM -->
                        <td
                          class="unit-item-column"
                          [style.width.px]="columnWidths[3]"
                          [style.display]="columns[3].visible ? '' : 'none'"
                        >
                          {{ programLocations?.unit_of_item ?? '-' }}
                        </td>
                        <!-- NO. ITEM -->
                        <td
                          class="num-item-column"
                          [style.width.px]="columnWidths[4]"
                        >
                          {{
                            program.num_of_items_program
                              | number : '1.0-0' ?? '-'
                          }}
                        </td>
                      </tr>
                    </table>
                  </td>
                </tr>
              </ng-container>
            </table>
          </td>
        </tr>
      </ng-container>
      <ng-container *ngIf="currentIndex > 1">
        <!-- PDO ROW -->
        <tr class="pdo-row" *ngFor="let pdo of tableData">
          <!-- PDO NAME -->
          <td
            class="td-headers"
            class="pdo-name-column sticky-left"
            [style.width.px]="columnWidths[0]"
            [style.display]="columns[0].visible ? '' : 'none'"
          >
            {{ pdo.name ?? '-' }}
          </td>
          <td class="td-headers" [colSpan]="tableHeaders.length - 1">
            <table class="w-100 h-100">
              <!-- PROGRAM ROW -->
              <ng-container
                *ngFor="
                  let program of pdo.pdo_programs;
                  let programIndex = index
                "
              >
                <tr class="program-row">
                  <!-- PDO PROGRAM -->
                  <td
                    class="pdo-program-column sticky-left"
                    [style.width.px]="columnWidths[1]"
                    [style.display]="columns[1].visible ? '' : 'none'"
                  >
                    {{ program.program ?? '-' }}
                  </td>
                  <td>
                    <table class="w-100 h-100">
                      <!-- LOCATION ROW -->
                      <tr
                        class="location-row"
                        *ngFor="
                          let programLocations of program?.pdo_program_locations
                        "
                      >
                        <!-- PROGRAM LOCATION -->
                        <td
                          class="location-column"
                          [style.width.px]="columnWidths[2]"
                          [style.display]="columns[2].visible ? '' : 'none'"
                        >
                          {{ programLocations?.location?.name ?? '-' }}
                        </td>
                        <td>
                          <table class="w-100 h-100">
                            <!-- UNIT ITEM ROW -->
                            <tr class="unit-item-row">
                              <!-- UNIT ITEM -->
                              <td
                                class="unit-item-column"
                                [style.width.px]="columnWidths[3]"
                                [style.display]="
                                  columns[3].visible ? '' : 'none'
                                "
                              >
                                {{ programLocations?.unit_of_item ?? '-' }}
                              </td>
                              <!-- NO. ITEM -->
                              <td
                                class="num-item-column"
                                [style.width.px]="columnWidths[4]"
                              >
                                {{
                                  pdo.num_of_items_pdo | number : '1.0-0' ?? '-'
                                }}
                              </td>
                            </tr>
                          </table>
                        </td>
                      </tr>
                    </table>
                  </td>
                </tr>
              </ng-container>
            </table>
          </td>
        </tr>
      </ng-container>
      <!-- Grand total-->
      <tr class="grand-total-row font-weight-bold">
        <td
          class="grand-total-column sticky-left"
          [style.width.px]="columnWidths[0]"
          [style.display]="columns[0].visible ? '' : 'none'"
        >
          Grand total
        </td>
        <td
          class="grand-total-column sticky-left"
          [style.width.px]="columnWidths[1]"
          [style.display]="columns[1].visible ? '' : 'none'"
        ></td>
        <td
          class="grand-total-column"
          [style.width.px]="columnWidths[2]"
          [style.display]="columns[2].visible ? '' : 'none'"
        ></td>
        <td
          class="grand-total-column"
          [style.width.px]="columnWidths[3]"
          [style.display]="columns[3].visible ? '' : 'none'"
        ></td>
        <td class="grand-total-column" [style.width.px]="columnWidths[4]">
          {{ grandTotal.totalNumItems | number : '1.0-0' }}
        </td>
      </tr>
    </tbody>
  </table>
</div>

Component.css

table,
th,
td {
  margin: 0;
  padding: 0;
  border-collapse: collapse;
  font-size: 12px;
}
th:not(:first-child) {
  position: sticky;
  top: 0;
  background-color: white;
}
th:first-child {
  position: sticky;
  top: 0;
  left: 0;
  z-index: 10;
  background-color: white;
}
.table-parent {
  min-width: 1440px;
}
.container-parent {
  max-height: 100vh;
}
.grand-total-column:not(:first-child) {
  position: sticky;
  bottom: 0;
  background-color: white;
}
.grand-total-column.sticky-left:first-child {
  position: sticky;
  bottom: 0;
  left: 0;
  z-index: 10;
  background-color: white;
}
.pdo-name-column.sticky-left {
  position: sticky;
  left: 0;
  background-color: white;
}

/* .grand-total-column.sticky-left:nth-child(2),
.table-headers.sticky-left:nth-child(2),
.pdo-program-column.sticky-left {
  position: sticky;
  left: 144px;
  background-color: white;
} */

.th-row {
  border-bottom: 2px solid #ccc;
}

.pdo-row,
.program-row:not(:last-child),
.location-row:not(:last-child),
.unit-item-row:not(:last-child) {
  border-bottom: 1px solid #ccc;
}
.grand-total-row {
  border-top: 2px solid #ccc;
}

.unit-item-column,
.grand-total-column:nth-child(4) {
  border-right: 2px solid #ccc;
}

.table-headers:nth-child(5),
.num-item-column,
.grand-total-column:not(:first-child) {
  text-align: right;
}

th,
.pdo-name-column,
.pdo-program-column,
.location-column,
.beneficiary-column,
.currency-column,
.num-beneficiaries-column,
.funding-needs-column,
.grand-total-column {
  padding: 1px;
}

For sample demo, click here

2

Answers


  1. try changing ng-container to div,
    and add "table-layout: fixed;" for table in css.
    i hope this helps

    Login or Signup to reply.
  2. creio eu que seu erro está ou no template, ou na estilização direta do table inves de deixar uma função feita para que a edição aplique em ambas e com prioridade( !!!! )

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