Search code examples
angulartypescriptcheckboxprimengprimeng-datatable

Assign current iteration item to ngModel inside pTemplate="header"?


How to assign current iteration item to ngModel inside pTemplate="header" ?

I am trying to achieve this on UI

  • If all the checkbox in a column are selected, the checkbox in the header should be selected as well.
  • If any checkbox in a column is unselected, the corresponding column header checkbox should be unselected.

UI

enter image description here

HTML

<p-panel header='Table Layout and Cells Selection'>

    <p-dataTable [value]="rowColumnData" *ngIf="renderCells" [scrollable]="true" scrollHeight="500px" frozenWidth="100px" unfrozenWidth="1750px"
        [loading]="loading" loadingIcon="fa-spinner">

        <!-- First column -->
        <p-column [style]="{'width':'100px', 'background-color': 'rgb(235, 237, 240)', 'text-align': 'left'}" frozen="true">
            <ng-template pTemplate="header">
                <p-checkbox binary="true" label="All" [(ngModel)]="selectAll" (onChange)="selectAllCells($event)" *ngIf="renderCells"></p-checkbox>
            </ng-template>

            <ng-template let-row="rowData" pTemplate="body">
                <p-checkbox binary="true" label={{row.ordrow}} [(ngModel)]="row.rowSelectAll" (onChange)='rowCheckboxSelectEvent(row, $event)'
                    pTooltip='{{row.ordrow}} - {{row.rowlabel}}'></p-checkbox>
            </ng-template>
        </p-column>

        <!-- Reminaing columns-->
        <p-column *ngFor="let col of columns; let i=index" [field]="col" [header]="col.ordcol" [style]="{'width':'75px', 'text-align': 'center'}">
            <!-- Header checkbox -->
            <ng-template pTemplate="header">
                <p-checkbox binary="true" label={{col.ordcol}} [(ngModel)]="HOW_TO_MAP???" (onChange)='columnCheckboxSelectEvent(columns[i], $event)'
                    pTooltip={{col.collabel}}></p-checkbox>
            </ng-template>

            <!-- Cells checkboxes -->
            <ng-template let-row="rowData" pTemplate="body">
                <p-checkbox binary="true" [(ngModel)]="row.columns[i].selected" [disabled]="row.columns[i].disabled" [style]="{'backgroundColor':'grey'}"
                    (onChange)='cellsCheckboxEvent(i)' *ngIf="row.columns[i]"></p-checkbox>
            </ng-template>
        </p-column>

    </p-dataTable>
</p-panel>

JSON

enter image description here

TypeScript - Model

    // Model for Row and columns

export class RowColumn {

    txstartdate: string;
    txenddate: string;
    reporttypecode: string;
    templatecode: string;
    tableversioncode: string;
    tableid: number;
    ordrow: string;
    rowlabel: string;
    iszaxisopen: string;
    ordzaxis: string;
    ordZLabel: string;

    // Array of columns
    columns: CellColumn[];
    selected: boolean;
    rowSelectAll: boolean;
    columnSelectAll2: boolean;  // I TRIED TO MAP THIS, BUT NOT WORKING !!
}

// Data point column
export class CellColumn {
    dvstartdate: string;
    dvenddate: string;
    disabled: string;
    ordcol: string;
    isrowkey: string;
    selected: boolean;
    collabel: string;

    // Array of Datapoint
    datapoints: Datapoint[];
    columnSelectAll: boolean;
}

export class Datapoint {
    trcid: number;
    datapointid: string;

    constructor(trcid: number, datapointid: string) {
        this.trcid = trcid;
        this.datapointid = datapointid;
    }
}

Solution

  • Add a boolean allSelected property to each of your item of your columns array and assign them false value.

    Then, you just have to call [(ngModel)]="col.allSelected" in your HTML and to update it whenever you click on a checkbox in a cell.

    ngOnInit() {
      this.columns = [
        { field: 'col1', header: '010', allSelected: false },
        { field: 'col2', header: '020', allSelected: false },
        { field: 'col3', header: '030', allSelected: false },
        { field: 'col4', header: '040', allSelected: false }
      ];
    
    
    }
    
    cellsCheckboxEvent(field) {
      // retrieve column index
      let colIndex = this.columns.map(function (item) {
        return item.field;
      }).indexOf(field);
    
      // check if there is a false value in column 'field'
      let isFalsePresentInColumn = this.data.map(function (row) {
        return row[field];
      }).indexOf(false) === -1;
    
      // update value of column header checkbox
      this.columns[colIndex].allSelected = isFalsePresentInColumn;
    }
    

    See StackBlitz