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
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
try changing ng-container to div,
and add "table-layout: fixed;" for table in css.
i hope this helps
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( !!!! )