You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 14嵌套HTML表格表头与数据列对齐问题求助

嵌套分组表格表头与数据列对齐问题(Angular 14)

问题背景

我需要通过嵌套HTML表格按PDO、Program、Location对表格数据进行分组,但当前遇到一个问题:当列未完全展开时,表格的<th>标签与嵌套的<td>标签无法对齐。我使用Angular 14框架开发,已经通过[style.width.px]="columnWidths[i]"确保<th>和<td>设置了相同的宽度,但对齐问题仍然存在。

问题表现

列未完全展开时,表头与数据列错位:

  • 表头状态:表头
  • 数据列状态:数据列

代码实现

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;
}

内容的提问来源于stack exchange,提问作者lance2k

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 09:40:55