Search code examples
angularangular6primengprimeng-turbotable

How to concatenate columns in a p-table with dynamic columns


My data source serves a json data file in the following format.

subjects.json

[
  {
    "subjectCode": "1111",
    "subjectTitle": "English Literature",
    "subjectGroup": "English",
    "status": "Available"
  },
  {
    "subjectCode": "2222",
    "subjectTitle": "Algebra III",
    "subjectGroup": "Mathematics",
    "status": "Not Available"
  }
]

Here is the interface class used to read the data file.

subject.model.ts

export interface Subject {
    subjectCode: string;
    subjectTitle: string;
    subjectGroup: string;
    status: string;
}

and the component file

subject.component.ts

export class SubjectComponent implements OnInit {

    searchResults: Subject[];

    // lots of other stuff

}

For UI design reasons, I need to display the subject code and subject title as a single column in the browser. This is easily done if I used static columns.

subject.component.html with static columns

<p-table [columns]="cols" [value]="searchResults">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th>Subject</th>
            <th>Group</th>
            <th>Status</th>          
        </tr>
     </ng-template>
     <ng-template pTemplate="body" let-rowData>
         <tr>
            <td>{{rowData.subjectCode}}&nbsp;{{rowData.subjectTitle}}</td>
            <td>{{rowData.subjectGroup}}</td>
            <td>{{rowData.status}}</td>
         </tr>
     </ng-template>
</p-table>

However, when I tried doing the same with dynamic columns, I cannot find a way to do it with the {{rowData[col.field]}} parameters that dynamic column uses, and I can't find any mention of how to do it in the PrimeNG documentation.

modified subject.component.ts to use dynamic columns

export class SubjectComponent implements OnInit {

    searchResults: Subject[];

    // table columns
    this.cols = [
        { field: 'subjectCode', header: 'Subject code'},
        { field: 'subjectTitle', header: 'Subject title'},
        { field: 'subjectGroup', header: 'Group'},
        { field: 'status', header: 'Status'}
    ];

// lots of other stuff
}

modified subject.component.html with dynamic columns

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

How do I concatenate the subject code and title from the interface into a single column in a p-table using dynamic columns?


Solution

  • You can check by column index or column field to skip render column, like this:

    <p-table [columns]="cols" [value]="data">
        <ng-template pTemplate="header" let-columns>
            <tr>
                <ng-container *ngFor="let col of columns; let i = index">
                    <th *ngIf="i != 1">
                        {{col.header}}
                        <p-sortIcon [field]="col.field"></p-sortIcon>
                    </th>
                </ng-container>
            </tr>
        </ng-template>
        <ng-template pTemplate="body" let-rowData let-columns="columns">
            <tr>
                <ng-container *ngFor="let col of columns; let i = index">
                    <td *ngIf="i == 0">
                        {{ rowData[col.field] + ' ' + rowData[columns[i + 1].field] }}
                    </td>
                    <td *ngIf="i > 1">
                        {{rowData[col.field]}}
                    </td>
                </ng-container>
            </tr>
        </ng-template>
    </p-table>
    

    or like this:

    <p-table [columns]="cols" [value]="data">
        <ng-template pTemplate="header" let-columns>
            <tr>
                <ng-container *ngFor="let col of columns">
                    <th *ngIf="col.field != 'subjectTitle'">
                        {{col.header}}
                        <p-sortIcon [field]="col.field"></p-sortIcon>
                    </th>
                </ng-container>
            </tr>
        </ng-template>
        <ng-template pTemplate="body" let-rowData let-columns="columns">
            <tr>
                <ng-container *ngFor="let col of columns; let i = index">
                    <td *ngIf="col.field == 'subjectCode'">
                        {{ rowData.subjectCode + ' ' + rowData.subjectTitle }}
                    </td>
                    <td *ngIf="col.field != 'subjectTitle' && col.field != 'subjectCode'">
                        {{rowData[col.field]}}
                    </td>
                </ng-container>
            </tr>
        </ng-template>
    </p-table>