PrimeNg <p-table> sorting
Asked Answered
K

5

12

I am using primeNg <p-table>. I want to implement sorting of data. What I did is below

sort.HTML

<p-table [columns]="cols" [value]="documents">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns" [pSortableColumn]="col.field">
                {{col.header}}
                <p-sortIcon [field]="col.field"></p-sortIcon>
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-doc>
        <tr>
            <td>
                {{doc.sName}}
            </td>

        <td>
                {{doc.sYear}}
            </td>
        <td>
                {{doc.sAge}}
            </td>
        <td>
                {{doc.sColor}}
            </td>        
        </tr>
    </ng-template>
</p-table>

sort.ts

this.cols = [
            { field: 'name', header: 'Name' },
            { field: 'year', header: 'Year' },
            { field: 'age', header: 'Age' },
            { field: 'color', header: 'Color' }
        ];

ngOnInit(){
    //made a service call and got data for

this.documents=[{
"sName":"Jhon",
"sYear":"1994",
"sAge":"20",
"sColor":"Red"
},
{
"sName":"Sam",
"sYear":"1996",
"sAge":"25",
"sColor":"Red"
},
{
"sName":"Anna",
"sYear":"1991",
"sAge":"21",
"sColor":"Green"
},
{
"sName":"Jhon",
"sYear":"1999",
"sAge":"25",
"sColor":"Blue"
},
{
"sName":"Betty",
"sYear":"1993",
"sAge":"35",
"sColor":"Red"
}]
}

As of now only Name field is getting sorted, how can I implement sorting in other columns as well? I used [pSortableColumn] but columns are not getting sorted, I am missing out of somepoint. Can you please guide me where I am wrong?

PS: I cannot used <p-dataTable>.

Keating answered 28/6, 2018 at 9:43 Comment(4)
First thing you need to change your data because in your documents array all object values are same.Channing
@pArthsavadiya corrected my post. Still sorting does not work.Keating
could you please create stackblitz.com/edit/primengChanning
@pArthsavadiya sorry cannot login to stackblitz from my organisation.Keating
A
20

For Sorting with Turbo table / p-table with fixed column try below code

                <p-table #dt [value]="data">
                <ng-template pTemplate="header">
                    <tr>
                        <th [pSortableColumn]="'Name'">Name
                            <p-sortIcon [field]="'Name'"></p-sortIcon>
                        </th>
                        <th [pSortableColumn]="'Age'">Age
                            <p-sortIcon [field]="'Age'"></p-sortIcon>
                        </th>
                        <th [pSortableColumn]="'Height'">Height
                            <p-sortIcon [field]="'Height'"></p-sortIcon>
                        </th>
                    </tr>
                </ng-template>
                <ng-template pTemplate="body" let-col>
                    <tr>
                        <td>{{col.Name}}</td>
                        <td>{{col.Age}}</td>
                        <td>{{col.Height}}</td>
                    </tr>
                </ng-template>
            </p-table>
Ashlar answered 26/7, 2018 at 7:50 Comment(1)
Thanks. Crazy this should be in the docs. Spent ages on this and followed the docs. It states that the value of pSortableColumn needs to match a data key, this makes sense, but why the single quotes!!!! Should be in the docs. If I missed it I read it too many timesReiss
R
10

if I got your question right, you are not asking to be able to sort multiple columns at the same time, but simply sorting is not working. In your code the problem is that you are specifying in the header of the table the following columns field to sort to:

[pSortableColumn]="col.field"

and these fields are defined as:

this.cols = [
            { field: 'name', header: 'Name' },    
            { field: 'year', header: 'Year' },
            { field: 'age', header: 'Age' },
            { field: 'color', header: 'Color' }
        ];

BUT your data is arriving with different names:

this.documents=[{
          "sName":"Jhon",
          "sYear":"1994",
          "sAge":"20",
          "sColor":"Red"
},
[...]

"name" != "sName" so your table is not capable to sort the data. In fact I'm surprised you say that the column "name" is sortable.

Just change the definition and the code will be working.

In any case, to allow also multi column sorting, I suggest to change the code as:

<p-table [columns]="cols" [value]="documents" sortMode="multiple">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns" [pSortableColumn]="col.field">
                {{col.header}}
                <p-sortIcon [field]="col.field"></p-sortIcon>
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-doc let-columns="columns">
        <tr>
            <td *ngFor="let col of columns">
                {{doc[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-table>

It is also more light and no change in the ts file is required, even if you take data from a web service since from the html file point of view you are always passing a "documents" object.

Roxieroxine answered 6/8, 2018 at 8:24 Comment(2)
How to call sort API instead of local sort on clicking on header?Vinnievinnitsa
You should add this as attribute of p-table: (sortFunction)="customSort($event)" [customSort]="true" and then from the application implement a customSort(event: sortEvent) function that does whatever you need (even call APIs if you need).Roxieroxine
S
1

You need to enable multi mode for sorting using sortMode="multiple" like this -

<p-table [columns]="cols" [value]="documents" sortMode="multiple">

Default sorting is executed on a single column, in order to enable multiple field sorting, set sortMode property to "multiple" and use metakey when clicking on another column.

For more information refer to documentation -

Streetman answered 28/6, 2018 at 9:49 Comment(3)
added sortMode="multiple" still columns other than 'Name' is not getting sorted.Keating
Follow the example from here primefaces.org/primeng/#/table/sortStreetman
Yes, i followed this post only. but I am loading pTemplate="body" from service response and in the example they are doing {{rowData[col.field]}}. Still i am facing the issue. @Pradeep JainKeating
P
1

The TurboTable it's OK

        <div class="table-responsive ">
        <p-table #turboTable [value]="claims" [rowHover]="true" [paginator]="true" [rows]="20" [showCurrentPageReport]="true" [first]="first"
                 currentPageReportTemplate="Reclamos de {first} a {last} de {totalRecords} registros" [rowsPerPageOptions]="[10,25,50]">
            <ng-template pTemplate="header">
                <tr>

                    <th pSortableColumn="id" width="8%">ID <p-sortIcon field="id"></p-sortIcon></th>

                    <th pSortableColumn="code" width="15%">CODE <p-sortIcon field="code"></p-sortIcon></th>

                    <th pSortableColumn="customerClaimDate" width="18%">FECHA RECLAMO CLIENTE <p-sortIcon field="customerClaimDate"></p-sortIcon></th>

                    <th pSortableColumn="claimDate" width="18%">FECHA CREACIÓN RECLAMO <p-sortIcon field="claimDate"></p-sortIcon></th>

                    <th pSortableColumn="maximumResponseDate" width="15%">FECHA MAX RESPUESTA <p-sortIcon field="maximumResponseDate"></p-sortIcon></th>

                    <th pSortableColumn="assignedUserName" width="17%">DERIVADO A <p-sortIcon field="assignedUserName" ></p-sortIcon></th>

                    <th pSortableColumn="state" width="10%">ESTADO <p-sortIcon field="state"></p-sortIcon></th>
                </tr>
            </ng-template>
            <ng-template pTemplate="body" let-tblreclamos>
                <tr>
                    <td>
                        <span>{{ tblreclamos.id }}</span>
                    </td>
                    <td>
                        <span><a [routerLink]="['edicion', tblreclamos.id]">{{ tblreclamos.code }}</a></span>
                    </td>
                    <td>
                        <span>{{ tblreclamos.customerClaimDate }}</span>
                    </td>
                    <td>
                        <span>{{ tblreclamos.claimDate }}</span>
                    </td>
                    <td>
                        <span>{{ tblreclamos.maximumResponseDate }}</span>
                    </td>
                    <td>
                        <span>{{ tblreclamos.assignedUserName }}</span>
                    </td>
                    <td>
                        <span>
                           <span [class]="'customer-badge'"
                                 *ngIf="tblreclamos.state==53">Borrador</span>
                          <span [class]="'customer-badge status-warning'"
                                *ngIf="tblreclamos.state==54">Pendiente</span>
                          <span [class]="'customer-badge status-success'"
                                *ngIf="tblreclamos.state== 55">Resuelto</span>
                          <span [class]="'customer-badge status-danger'"
                                *ngIf="tblreclamos.state==56">Anulado</span>

                        </span>
                    </td>
                </tr>
            </ng-template>


        </p-table>
    </div>
Penetrance answered 4/3, 2022 at 18:30 Comment(0)
B
0
  customSort(event: SortEvent) {
    if (this.isSorted == null || this.isSorted === undefined) {
      this.isSorted = true;
      this.sortTableData(event);
    } else if (this.isSorted == true) {
      this.isSorted = false;
      this.sortTableData(event);
    } else if (this.isSorted == false) {
      this.isSorted = null;
      this.products = [...this.initialValue];
      this.dt.reset();
    }
  }

  sortTableData(event) {
    event.data.sort((data1, data2) => {
      let value1 = data1[event.field];
      let value2 = data2[event.field];
      let result = null;
      if (value1 == null && value2 != null) result = -1;
      else if (value1 != null && value2 == null) result = 1;
      else if (value1 == null && value2 == null) result = 0;
      else if (typeof value1 === 'string' && typeof value2 === 'string')
        result = value1.localeCompare(value2);
      else result = value1 < value2 ? -1 : value1 > value2 ? 1 : 0;

      return event.order * result;
    });
  }
Buxton answered 23/3 at 15:26 Comment(1)
(sortFunction)="customSort($event)" [customSort]="true" [responsiveLayout]="scroll"Buxton

© 2022 - 2024 — McMap. All rights reserved.