Table - RowGroup It is easy to implement row grouping using the flexible template driven approach of the p-table. In this example, sorting is enabled by default to sort the data by brand initially and then a rowGroupMetadata object is created to represent how many rows a brand should span along with the rowIndex of the group. Similarly multiple field grouping can be implemented as well.

Subheader

Vin Year Color {{rowData.brand}} {{rowData.vin}} {{rowData.year}} {{rowData.color}}

Rowspan

Brand Vin Year Color {{rowData.brand}} {{rowData.vin}} {{rowData.year}} {{rowData.color}}
View on GitHub

export class TableRowGroupDemo implements OnInit {

    cars: Car[];

    rowGroupMetadata: any;

    constructor(private carService: CarService) { }

    ngOnInit() {
        this.carService.getCarsMedium().then(cars => {
            this.cars = cars;
            this.updateRowGroupMetaData();
        });
    }

    onSort() {
        this.updateRowGroupMetaData();
    }

    updateRowGroupMetaData() {
        this.rowGroupMetadata = {};
        if (this.cars) {
            for (let i = 0; i < this.cars.length; i++) {
                let rowData = this.cars[i];
                let brand = rowData.brand;
                if (i == 0) {
                    this.rowGroupMetadata[brand] = { index: 0, size: 1 };
                }
                else {
                    let previousRowData = this.cars[i - 1];
                    let previousRowGroup = previousRowData.brand;
                    if (brand === previousRowGroup)
                        this.rowGroupMetadata[brand].size++;
                    else
                        this.rowGroupMetadata[brand] = { index: i, size: 1 };
                }
            }
        }
    }
    
}

View on GitHub

<h3 class="first">Subheader</h3>
<p-table [value]="cars" sortField="brand" sortMode="single" (onSort)="onSort()">
    <ng-template pTemplate="header">
        <tr>
            <th>Vin</th>
            <th>Year</th>
            <th>Color</th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowData let-rowIndex="rowIndex">
        <tr class="ui-widget-header" *ngIf="rowGroupMetadata[rowData.brand].index === rowIndex">
            <td colspan="3">
                <span style="font-weight:bold">{{rowData.brand}}</span>
            </td>                
        </tr>
        <tr>
            <td>{{rowData.vin}}</td>
            <td>{{rowData.year}}</td>
            <td>{{rowData.color}}</td>
        </tr>
    </ng-template>
</p-table>

<h3>Rowspan</h3>
<p-table [value]="cars" sortField="brand" sortMode="single" (onSort)="onSort()">
    <ng-template pTemplate="header">
        <tr>
            <th>Brand</th>
            <th>Vin</th>
            <th>Year</th>
            <th>Color</th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowData let-rowIndex="rowIndex">
        <tr>
            <td *ngIf="rowGroupMetadata[rowData.brand].index === rowIndex" [attr.rowspan]="rowGroupMetadata[rowData.brand].size">
                {{rowData.brand}}
            </td>
            <td>{{rowData.vin}}</td>
            <td>{{rowData.year}}</td>
            <td>{{rowData.color}}</td>
        </tr>
    </ng-template>
</p-table>