How to add frozen columns to primeNG when rows are rendering dynamically in Angular
Asked Answered
S

4

4

I was looking for help to add the frozen columns feature in my primeng table where the columns and rows are dynamically rendered.

I do have a config( isPK: true) that came from data on which I want to make frozen columns.

I have tried following stackblitz but I cannot found a solution to match the example given in the documentation of PrimeNG

Thanks, @Owen for the answer but now If I try to add an extra column in the HTML itself it is getting doubled like this,

https://stackblitz.com/edit/primeng-tablescroll-demo-jvmrfs enter image description here

Spleen answered 17/5, 2021 at 13:48 Comment(2)
Do you mean, non editable? if yes, then you can provide value to cell but in non-edited mode. Ex. The pInputText that you used can be in disabled mode on certain conditions.Stannic
No Frozen columns primefaces.org/primeng/showcase/#/table/scrollSpleen
G
2

You should use templating for frozen data as described in documentation in Templates section:

frozenheader: Content of the thead element in frozen side.

frozenbody: Content of the tbody element in frozen side.

Here is a working example. Table body looks weird but because you are using dynamic columns, there must be a match between columns and data.

Like this example for Dynamic columns from documentation.

Goldofpleasure answered 28/5, 2021 at 17:26 Comment(2)
Why template is necessary? alignFrozen="left" pFrozenColumn [frozen]="true"> for dynamic columns doesn't seem to work for meCayser
I get Can't bind to 'frozen' since it isn't a known property of 'th'Cayser
F
2

Its sometimes easier to move from a working example and generate what you want step after another. Something like below

<p-button class="secondary" label="Add row" (onClick)="onAddRow(card)"></p-button>


<p-table #dt [columns]="scrollableCols" [frozenColumns]="frozenCols" [value]="card" [scrollable]="true"
  scrollHeight="200px" frozenWidth="200px">
  <ng-template pTemplate="colgroup" let-columns>
    <colgroup>
      <col *ngFor="let col of columns" style="width:200px">
    </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">
    <ng-container *ngFor="let tr of card[0].rows; let i = index">
      <tr>
        <ng-container *ngFor="let attr of card[0].attributes; let j = index">
          <td
            [ngClass]="{'error-block': 
                                                            (card[0].rows[i].validated == true && isSubmitted && card[0].rows[i][j].value === '' && card[0].rows[i][j].required === 'true') ||
                                                            (card[0].rows[i].validated == true && isSubmitted && card[0].rows[i][j].value.length < card[0].rows[i][j].minLength)}">
            <ng-container *ngIf="attr.type === 'string'">
              <input pInputText style="width: 100%;"
                                                                    (ngModelChange)="onChange($event, i, j, card)"
                                                                    type="text"
                                                                    [(ngModel)]="card[0].rows[i][j].value"
                                                                    [maxlength]="card[0].rows[i][j].maxLength"
                                                                    [minlength]="card[0].rows[i][j].minLength"/>
              <span class="error required-error" *ngIf="card[0].rows[i].validated == true && isSubmitted && card[0].rows[i][j].value === '' && card[0].rows[i][j].required === 'true'">
                                                                    <!-- This field is required. -->
                                                                </span>
              <span class="error minlength-error" *ngIf="card[0].rows[i].validated == true && isSubmitted && card[0].rows[i][j].value.length < card[0].rows[i][j].minLength">
                                                                    <!-- Please enter {{card[0].rows[i][j].minLength}} characters to continue. -->
                                                                </span>
              <!-- {{i}}, {{j}} {{card[0].rows[i][j] | json}} -->
            </ng-container>
            <ng-container *ngIf="attr.values">
              <select class="dropdown" [(ngModel)]="card[0].rows[i][j].value" (ngModelChange)="onChange($event, i, j, card)">
                                                                    <option *ngFor="let option of attr.values">{{option}}</option>
                                                                </select>
              <span class="error required-error" *ngIf="card[0].rows[i].validated == true && isSubmitted && card[0].rows[i][j].value === '' && card[0].rows[i][j].required === 'true'">
                                                                    <!-- This field is required. -->
                                                                </span>
            </ng-container>
            <ng-container *ngIf="attr.type === 'date'">
              <p-calendar [readonlyInput]="true" panelStyleClass="datepicker" appendTo="body"
                inputStyleClass="date-input" [(ngModel)]="card[0].rows[i][j].value"
                (ngModelChange)="onChange($event, i, j, card)" dateFormat="mm/dd/yy"></p-calendar>
            </ng-container>
          </td>
        </ng-container>
      </tr>
    </ng-container>
  </ng-template>
</p-table>

See Demo Here

Faretheewell answered 17/5, 2021 at 15:49 Comment(1)
Thanks a lot, Owen but now if I would like to add an extra column directly in HTML it will be doubled directly like this, stackblitz.com/edit/primeng-tablescroll-demo-jvmrfsSpleen
G
2

You should use templating for frozen data as described in documentation in Templates section:

frozenheader: Content of the thead element in frozen side.

frozenbody: Content of the tbody element in frozen side.

Here is a working example. Table body looks weird but because you are using dynamic columns, there must be a match between columns and data.

Like this example for Dynamic columns from documentation.

Goldofpleasure answered 28/5, 2021 at 17:26 Comment(2)
Why template is necessary? alignFrozen="left" pFrozenColumn [frozen]="true"> for dynamic columns doesn't seem to work for meCayser
I get Can't bind to 'frozen' since it isn't a known property of 'th'Cayser
N
2

I added a property isFrozenColumn in the column definition like that and it worked perfectly
See Frozen Columns parte in https://www.primefaces.org/primeng/showcase/#/table/scroll

columns = [
        {
            field: 'name',
            header: 'Name',
            isFrozenColumn: true
        },
        {
            field: 'Phone',
            header: 'phone',
            isFrozenColumn: false
        }]

Header

<th alignFrozen="left"  
        pFrozenColumn 
        [frozen]="true">Actions</th>
<ng-container *ngFor="let col of columns">
    <th class="width-small"
        alignFrozen="left"  
        pFrozenColumn 
        [frozen]="col?.isFrozenColumn">
        <p-header>{{ col.header }}</p-header>
    </th>
</ng-container>

Body

<td alignFrozen="left"  
        pFrozenColumn 
        [frozen]="true">
    <a type="button" 
        (click)="edit(item)">Edit</a>
    </td>
<ng-container *ngFor="let col of columns">
    <td alignFrozen="left"  
        pFrozenColumn 
        [frozen]="col?.isFrozenColumn">
        {{ item[col.field] }}
    </td>
</ng-container>
Nodular answered 8/2, 2022 at 12:26 Comment(0)
C
0

Add pFrozenColumn directive to the column where you need to make the column as frozen ex: <td pFrozenColumn></td>

and the add the properties [scrollable]="true" scrollDirection="horizontal" with in it.

like the code as follows:

<p-table [value]="list" [scrollable]="true" scrollDirection="horizontal" >
     <ng-template pTemplate="body">
          <tr>
             <td pFrozenColumn >
             </td>
          </tr>
     </ng-template>
</p-table>
Champlain answered 5/4 at 7:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.