cdk virtual scrolling with sticky header html table angular

6.1k views Asked by At

I am getting more than 30000 records from backend to list in frontend, So using cdk-virtual-scroll I can able to achieve this. I have created normal table enclosed with cdk-tag

          <cdk-virtual-scroll-viewport [itemSize] = "20">
            <div class="result_table">
             <table class="dataframe" border="1">
            <thead>
              <tr>
                <th >
                  Name
                </th>
                <th >
                  Description
                </th>
                <th >
                  Group
                </th>
                <th >
                  Data
                </th>
              </tr>
            </thead>
                <tbody>
                  <tr *cdkVirtualFor ="let data of address_obj_data_holder | filter:searchAddr">
                    <td >
                      {{data.name}}
                    </td>
                                             
                    <td >
                      {{data.description}}
                    </td>
                    <td >
                     {{data.group}}
                    </td> 
                    <td >
                     {{data.data}}
                    </td>
                  </tr>
                </tbody>
              </table>
            </div>
          </cdk-virtual-scroll-viewport>

If I do like this, table header also scrolls when I scrolls down, and If I do like,

          <cdk-virtual-scroll-viewport [itemSize] = "20">
            <div class="result_table">
             <table class="dataframe" border="1">
            <thead>
              <tr>
                <th style="width: 20% !important;">
                  Name
                </th>
                <th style="width: 40% !important;">
                  Description
                </th>
                <th style="width: 20% !important;">
                  Group
                </th>
                <th style="width: 20% !important;">
                  Data
                </th>
              </tr>
            </thead>
                <tbody>
                  <tr *cdkVirtualFor ="let data of address_obj_data_holder | filter:searchAddr">
                    <td style="width: 20% !important;">
                      {{data.name}}
                    </td>
                                             
                    <td style="width: 40% !important;">
                      {{data.description}}
                    </td>
                    <td style="width: 20% !important;">
                    {{data.group}}
                    </td> 
                    <td style="width: 20% !important;">
                      {{data.data}}
                    </td>
                  </tr>
                </tbody>
              </table>
            </div>
          </cdk-virtual-scroll-viewport>

width of header and tbody is slightly different both are not in same width as we have scroll in below body alone. Can some one help me to fix this alignment issue.

enter image description here

3

There are 3 answers

1
Abdur Raziq Khan On

If you are looking to make the header sticky of table and you are using cdk-virtual-scroll-viewport, then try this:

table { overflow: auto; }
thead { position: sticky; top: 0; }
0
Oleg Bondarenko On

Each header position could be adjusted with the method

 <th [style.top]="inverseOfTranslation"> ... </th>

And related code

 @ViewChild(CdkVirtualScrollViewport, { static: false })
  public viewPort: CdkVirtualScrollViewport;

public get inverseOfTranslation(): string {
    if (!this.viewPort) {
      return '-0px';
    }
    const offset = this.viewPort.getOffsetToRenderedContentStart();

    return `-${offset}px`;
  }
1
Subhankar Roy On

`<th [style.top]="inverseOfTranslation()" style="width:50px;">LOT No.

@ViewChild(CdkVirtualScrollViewport) viewport!: CdkVirtualScrollViewport;
    inverseOfTranslation(): string {
        if (!this.viewport) {
          return '-0px';
        }
        const offset = this.viewport.getOffsetToRenderedContentStart();
    
        return `-${offset}px`;
      }
thead tr:first-child th { position: sticky; top: 0; background-color: inherit; }
<th [style.top]="inverseOfTranslation()" style="width:50px;">LOT No.</th>
`