angularprimeng

having problem with primeng table height and width issue


i need to have a table with 50 rows scroll, but it must be fitted perfectly in ng-content, when i try to manipulate table height i fail.

table component

<p-panel header="აქტიური სია" @myInsertRemoveTrigger>
  <div #tableDiv class="">
    <p-table
      [columns]="activeListTableColumns"
      [value]="tableData.data"
      dataKey="id"
      [paginator]="true"
      [rows]="20"
      [scrollable]="true"
      [scrollHeight]="'800px'"
      [lazy]="true"
      (onLazyLoad)="lazyLoad($event)"
      [totalRecords]="tableData.total"
      [tableStyle]="{ 'min-width': '150rem' }">
      <ng-template pTemplate="header" let-columns>
        <tr>
          @for(column of columns; track $index) {
            <th>{{ column.header }}</th>
          }
        </tr>
      </ng-template>
      <ng-template pTemplate="body" let-rowData let-columns="columns">
        <tr>
          @for(column of columns; track $index) {
            <td>{{ rowData[column.field] }}</td>
          }
        </tr>
      </ng-template>
    </p-table>
  </div>
</p-panel>

layout component

<main class="flex flex-column gap-1 h-full">
  <p-menubar class="fadein animation-duration-2000 animation-ease-in-out" [model]="menuItems">
    <ng-template pTemplate="start">
      <div class="flex flex-row justify-content-between align-items-center gap-1">
        <img ngSrc="assets/svg/tbc.svg" height="40" class="mr-2" alt="tbc" width="40"/>
        <span class="font-bold">Risk Check Engine</span>
      </div>
    </ng-template>
    <ng-template pTemplate="end">
        <p-chip styleClass="pl-0 pr-3">
          <span class="bg-primary border-circle w-2rem h-2rem flex align-items-center justify-content-center">{{authService.getUser().fullName[0]}}</span>
          <span class="ml-2 font-medium">{{authService.getUser().fullName}}</span>
        </p-chip>
        <p-button icon="pi pi-sign-out" [rounded]="true" severity="danger" [outlined]="true" (click)="logout()"></p-button>
    </ng-template>
  </p-menubar>

  <div class="fadein animation-duration-2000 animation-ease-in-out h-full">
    <ng-content></ng-content>
  </div>
</main>

i have tried setting [scrollHeight]="'flex'" and also [scrollHeight]="calcHeight()", but nothing seems to work. my only solution to this is to set static height, for example 800px and have some bits of whitespace left over at end of the page, that is bugging me.

does anybody have this issue or any solves for this ?


Solution

  • Since I couldn’t find an answer here, I’d like to share the solution I’ve been using ever since. There isn’t a direct and easy way (debatable) to dynamically adjust the height of a table. What I’ve done is wrap my table in a div and listen to that div’s size changes using a ResizeObserver. Here’s the solution:


    HTML Setup:

    Wrap your p-table inside a div and give it a #tableDiv reference

    <div class="flex-grow overflow-hidden" #tableDiv>
      <p-table
        [scrollable]="true"
        [scrollHeight]="tableHeight()"
        [responsiveLayout]="'scroll'"
      >
        <!-- table templates go here -->
      </p-table>
    </div>
    

    TypeScript Logic:

    Use a ResizeObserver to monitor the size of the div. Dynamically calculate the height of the table by deducting the heights of other elements (like the paginator and caption)

    tableHeight: WritableSignal<string> = signal('100px') // initial 100px for signal to have a value, optional but nice to have
    
    ngAfterViewInit() {
        this.setupDynamicHeight();
    }
    
    setupDynamicHeight(): void {
        this.resizeObserver = new ResizeObserver(() => {
            this.calculateTableHeight();
        });
    
        this.resizeObserver.observe(this.tableDiv.nativeElement);
        this.calculateTableHeight(); // Initial calculation
    }
    
    private calculateTableHeight(): void {
        const tableHeight = this.tableDiv.nativeElement.clientHeight;
        const paginatorHeight = 49; // Adjust as needed
        const captionHeight = 59;  // Adjust as needed
        this.tableHeight.set(`${tableHeight - paginatorHeight - captionHeight}px`);
    }
    

    Explanation:

    1. Container Wrapping: The table is wrapped inside a div with #tableDiv, allowing its size to be observed.
    2. Dynamic Height Calculation: The ResizeObserver recalculates the table height every time the div size changes.
    3. Adjust for Extra Elements: Deduct the heights of any additional elements like paginators or captions to get the correct table height.

    This approach ensures your table adapts dynamically to changes in its parent container.

    Feel free to ask if you need clarification or enhancements and if you have a better solution please write an answer bellow for other curious devs to see !