1
votes

I want to try out the scrollable table from PrimeNG. For the moment I'd just like to display some data and let the user edit these. So I wanted to start off with a table that contains a header and a few rows of cells without data. The cells in the frozenColumns-area should not be editable, the ones in the scrollable-area should be. Now I tried around and it is looking quite weird:

enter image description here

Now the static content is displayed in both sections (scrollable and frozen), I could not change the cell-width of the scrollable-area and the table-size is different, aswell as the row-alignment. What am I doing wrong? How should I properly create this table? I tried to follow the examples on PrimeNG, but that did not help me out. I am using Angular 7 btw.

The code:

My HTML:

<p-table [columns]="scrollableCols" [frozenColumns]="frozenCols" [value]="items" [scrollable]="true" scrollHeight="400px" frozenWidth="400px">

  <ng-template pTemplate="colgroup" let-coumns>
    <colgroup>
      <col *ngFor="let col of columns">
    </colgroup>
  </ng-template>

  <ng-template pTemplate="header" let-columns>
      <tr>
          <th *ngFor="let col of columns">
              {{col.header}}
          </th>
      </tr>
  </ng-template>


  <ng-template pTemplate="body" let-rowData let-columns="columns">
    <!-- procude some more rows (without data) -->
    <tr *ngFor="let row of scrollableCols">

      <!-- static columns should not be editable -->
      <td *ngFor="let static of frozenCols">
        frozenColumn
      </td>

      <!-- scrollable columns should be editable -->
      <ng-template ngFor let-col [ngForOf]="columns">
      <td pEditableColumn>
          <p-cellEditor>
              <ng-template pTemplate="input">
                  <input pInputText type="text" [(ngModel)]="col.header" [style]="{'width':'100%'}">
              </ng-template>
              <ng-template pTemplate="output">
                  {{col.field}}
              </ng-template>
          </p-cellEditor>
      </td>
    </ng-template>

    </tr>

  </ng-template>
</p-table>

I have the following code in my component:

 cols: any[];
 scrollableCols: any[];
 frozenCols: any[];

 items: any[];

 ngOnInit() {
 this.cols = [
  { field: 'fixedCol1', header: 'Fixed-Col 1' },
  { field: 'fixedCol2', header: 'Fixed-Col 2' },
  { field: 'fixedCol3', header: 'Fixed-Col 3' },
  { field: 'scrollableCol1', header: 'Scrollable Col 1' },
  { field: 'scrollableCol2', header: 'Scrollable Col 2' },
  { field: 'scrollableCol3', header: 'Scrollable Col 3' }
 ];

 this.frozenCols = [
  { field: 'fixedCol1', header: 'Fixed-Col 1' },
  { field: 'fixedCol2', header: 'Fixed-Col 2' },
  { field: 'fixedCol3', header: 'Fixed-Col 3' }
 ];
 this.scrollableCols = [
  { field: 'scrollableCol1', header: 'Scrollable Col 1' },
  { field: 'scrollableCol2', header: 'Scrollable Col 2' },
  { field: 'scrollableCol3', header: 'Scrollable Col 3' },
  { field: 'scrollableCol1', header: 'Scrollable Col 1' },
  { field: 'scrollableCol2', header: 'Scrollable Col 2' },
  { field: 'scrollableCol3', header: 'Scrollable Col 3' },
  { field: 'scrollableCol1', header: 'Scrollable Col 1' },
  { field: 'scrollableCol2', header: 'Scrollable Col 2' },
  { field: 'scrollableCol3', header: 'Scrollable Col 3' },
  { field: 'scrollableCol1', header: 'Scrollable Col 1' },
  { field: 'scrollableCol2', header: 'Scrollable Col 2' },
  { field: 'scrollableCol3', header: 'Scrollable Col 3' },
  { field: 'scrollableCol1', header: 'Scrollable Col 1' },
  { field: 'scrollableCol2', header: 'Scrollable Col 2' },
  { field: 'scrollableCol3', header: 'Scrollable Col 3' },
  { field: 'scrollableCol1', header: 'Scrollable Col 1' },
  { field: 'scrollableCol2', header: 'Scrollable Col 2' },
  { field: 'scrollableCol3', header: 'Scrollable Col 3' },
  { field: 'scrollableCol1', header: 'Scrollable Col 1' },
  { field: 'scrollableCol2', header: 'Scrollable Col 2' },
  { field: 'scrollableCol3', header: 'Scrollable Col 3' }
 ];
 //Items-array should contain a value for the table to be created, although it is not used
 this.items = [{placeholder: "placeholder"}];

}
3

3 Answers

1
votes

The body should be:

<ng-template pTemplate="body" let-rowData let-columns="columns">
        <tr>
            <td pEditableColumn *ngFor="let col of columns">
        <span *ngIf="col.frozen_col">frozenColumn</span>
        <p-cellEditor *ngIf="!col.frozen_col">
                        <ng-template pTemplate="input">
                            <input pInputText type="text" [(ngModel)]="col.header" [style]="{'width':'100%'}">
              </ng-template>
              <ng-template pTemplate="output">
                  {{ col.field }}
              </ng-template>
          </p-cellEditor>
            </td>
        </tr>
    </ng-template>

because let-columns="columns" include frozen and unfrozen columns.

And add frozen_col flag to switch HTML

this.frozenCols = [
      { field: 'fixedCol1', header: 'Fixed-Col 1', frozen_col: true },
      { field: 'fixedCol2', header: 'Fixed-Col 2', frozen_col: true },
      { field: 'fixedCol3', header: 'Fixed-Col 3', frozen_col: true }
    ];

Here is demo

1
votes

You can use this method and can call it in subscribe in case of fetching data from an api:

makeRowsSameHeight() {
   setTimeout(() => {
       if (document.getElementsByClassName('ui-table-scrollable-wrapper').length) {
           let wrapper = document.getElementsByClassName('ui-table-scrollable-wrapper');
           for (var i = 0; i < wrapper.length; i++) {
              let w = wrapper.item(i) as HTMLElement;
              let frozen_rows: any = w.querySelectorAll('.ui-table-frozen-view tr');
              let unfrozen_rows: any = w.querySelectorAll('.ui-table-unfrozen-view tr');
              for (let i = 0; i < frozen_rows.length; i++) {
                 if (frozen_rows[i].clientHeight > unfrozen_rows[i].clientHeight) {
                    unfrozen_rows[i].style.height = frozen_rows[i].clientHeight+"px";
                    } 
                 else if (frozen_rows[i].clientHeight < unfrozen_rows[i].clientHeight) 
                 {
                    frozen_rows[i].style.height = unfrozen_rows[i].clientHeight+"px";
                 }
               }
             }
           }
        });
      }

And call it in:

this.someapiservice.get().subscribe(result => {
        .....
        this.makeRowsSameHeight();
    });

I hope this helps.

0
votes

For latest version of primeng 11.4.1, following code is useful.

  makeRowsSameHeight(){
setTimeout(() => {
  if (document.getElementsByClassName('p-datatable-scrollable-wrapper').length) {
      let wrapper = document.getElementsByClassName('p-datatable-scrollable-wrapper');
      for (var i = 0; i < wrapper.length; i++) {
         let w = wrapper.item(i) as HTMLElement;
         let frozen_rows: any = w.querySelectorAll('.p-datatable-frozen-view tr');
         let unfrozen_rows: any = w.querySelectorAll('.p-datatable-unfrozen-view tr');
         for (let i = 0; i < frozen_rows.length; i++) {
            if (frozen_rows[i].clientHeight > unfrozen_rows[i].clientHeight) {
               unfrozen_rows[i].style.height = frozen_rows[i].clientHeight+"px";
               }
            else if (frozen_rows[i].clientHeight < unfrozen_rows[i].clientHeight)
            {
               frozen_rows[i].style.height = unfrozen_rows[i].clientHeight+"px";
            }
          }
        }
      }
   });

}