I am rendering the table using angular primeNg based on a condition. All the headers and values are coming dynamically. The table data is getting displayed properly. However the sorting is not working. I have used [pSortableColumn]="header". I can see the icons are moving upwords and downwards but the values are sorted. Attaching the code and data for reference.
getColumnHeaders(dataList: any[]): string[] {
if (dataList.length > 0) {
return Object.keys(dataList[0]);
} else {
return [];
}
}
<div class="card-tablelist mb-3" *ngFor="let singleObject of Data; index as i">
<div *ngIf="singleObject.DashboardDto.alertType!='Hybrid'">
<p-card class="alert-cardslist"
*ngIf="singleObject.DashboardDto as singleKey">
<ng-template pTemplate="header">
Alerts
</ng-template>
<ng-template pTemplate="content">
<div class="grid-data">
<p-table #dt1 [value]="singleKey.dataList" styleClass="p-datatable-gridlines"
[tableStyle]="{'min-width': '50rem'}" [sortable]="true">
<ng-template pTemplate="header">
<tr>
<th
*ngFor="let header of getColumnHeaders(singleKey.dataList)" [pSortableColumn]="header">
{{header}} <p-sortIcon [field]="header"></p-sortIcon> </th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-data>
<tr>
<td [ngClass]="{'text-left': data[header].alignment==='Left', 'text-right':data[header].alignment==='Right'}"
*ngFor="let header of getColumnHeaders(singleKey.dataList)">
{{data[header].value}}
</td>
</tr>
</ng-template>
</p-table>
</div>
</ng-template>
</p-card>
</div>
</div>
{
"data": [
{
DashboardDto :{
"companyName": "ABC Company Limited",
"alertType": "Standard",
"alertTypeComputed": "High",
"isCriticalAlert": 1,
"dataList": [
{
"Company Name": {
"value": ABC Company Limited",
"alignment": "Left"
},
"Unit": {
"value": "Lakh",
"alignment": "Left"
},
"Ratio": {
"value": "0",
"alignment": "Right"
},
"Period Ends on": {
"value": "31-Mar-2025",
"alignment": "Left"
}
},
{
"Company Name": {
"value": "ABC Company Limited",
"alignment": "Left"
},
"Unit": {
"value": "Crore",
"alignment": "Left"
},
"Ratio": {
"value": "0",
"alignment": "Right"
},
"Period Ends on": {
"value": "31-Mar-2024",
"alignment": "Left"
}
},
{
"Company Name": {
"value": "ABC Company Limited",
"alignment": "Left"
},
"Unit": {
"value": "Lakh",
"alignment": "Left"
},
"Ratio": {
"value": "1",
"alignment": "Right"
},
"Period Ends on": {
"value": "31-Mar-2023",
"alignment": "Left"
}
}
]
}
}
]
}
I am new to angular looking for suggestions. Thanks in advance.
This happens because your data is structured as:
{
"Company Name": {
"value": "ABC Company Limited",
"alignment": "Left"
}
}
But PrimeNG sorting expects flat fields, like:
{
"Company Name": "ABC Company Limited"
}
pSortableColumn
is pointing to header
(e.g., "Company Name"
), but it tries to sort using the raw object
You need to transform dataList
into a flat format, where each cell is just the .value
. For example:
[
{
"Company Name": "ABC Company Limited",
"Unit": "Lakh",
"Ratio": "0",
"Period Ends on": "31-Mar-2025"
},
//...your other objects
]
Use transformDataList
before passing to p-table
<p-table
#dt1
[value]="transformDataList(singleKey.dataList)"
[tableStyle]="{ 'min-width': '50rem' }"
[sortable]="true"
styleClass="p-datatable-gridlines"
>
<ng-template pTemplate="header">
<tr>
<th
*ngFor="let header of getColumnHeaders(singleKey.dataList)"
[pSortableColumn]="header"
>
{{ header }}
<p-sortIcon [field]="header"></p-sortIcon>
</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-data>
<tr>
<td
*ngFor="let header of getColumnHeaders(singleKey.dataList)"
class="text-left"
>
{{ data[header] }}
</td>
</tr>
</ng-template>
</p-table>
Add a transformer
transformDataList(dataList: any[]): any[] {
return dataList.map(row => {
const flatRow: any = {};
for (const key in row) {
if (row[key] && typeof row[key] === 'object' && 'value' in row[key]) {
flatRow[key] = row[key].value;
} else {
flatRow[key] = row[key]; // fallback
}
}
return flatRow;
});
}
By this your sorting will work, but you lose the .alignment
info in this approach. If you still need it (e.g., to set left/right alignment), you can store the raw object separately and use it only for styling, not data rendering.