Highlight cells and header if value of a cell is changed from its original value

139 Views Asked by At

I am using primeng table cell edit. My code is as follows:

<div class="card">
    <p-table [value]="products" dataKey="id" [tableStyle]="{ 'min-width': '50rem' }">
        <ng-template pTemplate="header">
            <tr>
                <th style="width:25%">Code</th>
                <th style="width:25%">Name</th>
                <th style="width:25%">Inventory Status</th>
                <th style="width:25%">Price</th>
            </tr>
        </ng-template>
        <ng-template pTemplate="body" let-product let-editing="editing">
            <tr>
                <td [pEditableColumn]="product.code" pEditableColumnField="code">
                    <p-cellEditor>
                        <ng-template pTemplate="input">
                            <input pInputText type="text" [(ngModel)]="product.code" />
                        </ng-template>
                        <ng-template pTemplate="output">
                            {{ product.code }}
                        </ng-template>
                    </p-cellEditor>
                </td>
                <td [pEditableColumn]="product.name" pEditableColumnField="name">
                    <p-cellEditor>
                        <ng-template pTemplate="input">
                            <input pInputText type="text" [(ngModel)]="product.name" required />
                        </ng-template>
                        <ng-template pTemplate="output">
                            {{ product.name }}
                        </ng-template>
                    </p-cellEditor>
                </td>
                <td [pEditableColumn]="product.inventoryStatus" pEditableColumnField="inventoryStatus">
                    <p-cellEditor>
                        <ng-template pTemplate="input">
                            <input pInputText [(ngModel)]="product.inventoryStatus" />
                        </ng-template>
                        <ng-template pTemplate="output">
                            {{ product.inventoryStatus }}
                        </ng-template>
                    </p-cellEditor>
                </td>
                <td [pEditableColumn]="product.price" pEditableColumnField="price">
                    <p-cellEditor>
                        <ng-template pTemplate="input">
                            <input pInputText type="text" [(ngModel)]="product.price" />
                        </ng-template>
                        <ng-template pTemplate="output">
                            {{ product.price | currency: 'USD' }}
                        </ng-template>
                    </p-cellEditor>
                </td>
            </tr>
        </ng-template>
    </p-table>
</div>

TS:

import { ProductService } from '../../service/productservice';

@Component({
    selector: 'table-cell-edit-demo',
    templateUrl: 'table-cell-edit-demo.html'
})
export class TableCellEditDemo implements OnInit {
    products!: Product[];

    constructor(private productService: ProductService) {}

    ngOnInit() {
        this.productService.getProductsMini().then((data) => {
            this.products = data;
        });
    }
}

Stackblitz:

https://stackblitz.com/run?file=src%2Fapp%2Fdemo%2Ftable-cell-edit-demo.html

Cell Edit is working fine. I want to highlight with red color those particular cells and respective header in non editable mode if value of any particular cell is changed from it's original value. How can I do that?

1

There are 1 best solutions below

0
Mouayad_Al On

In order to colorize the edited cell in your component's HTML, you can follow these steps:

  1. Add a template reference variable #rows to the <tr> element to read the rows using @ViewChildren. This will allow you to access the rows in your component.

    <tr #rows>
    
  2. Modify the <td> elements where you want to track edits by adding an [id] attribute. The [id] attribute should be set as a combination of the property and the rowIndex, for example: [id]="'name'+index".

    <td pEditableColumn [id]="'name' + ri">
    
  3. Inside the <input> element that represents the editable field, add (ngModelChange) to listen for changes in the input value. When the value changes, call a method such as colorizeEditedCell(rowIndex, fieldName) and pass the rowIndex and fieldName as parameters.

    <input pInputText type="text" [(ngModel)]="product.name" (ngModelChange)="colorizeEditedCell(ri,'name')" required />
    
  4. Add an @ViewChildren decorator to your component class to read the rows using the template reference variable #rows:

    @ViewChildren('rows') rows: QueryList<ElementRef<HTMLTableRowElement>>;
    
  5. Inject the Renderer2 into your component's constructor to use it for manipulating the DOM:

    constructor(private _renderer2: Renderer2) {}
    
  6. Define the colorizeEditedCell function in your component to set the background color of the edited cell. This function takes the rowIndex and fieldName as parameters.

    colorizeEditedCell(rowIndex: number, fieldName: string) {
      const cols = this.rows.get(rowIndex).nativeElement.cells;
      for (let colIndex = 0; colIndex < cols.length; colIndex++) {
        const col = cols.item(colIndex);
        if (col.id == fieldName + rowIndex) {
          this._renderer2.setStyle(col, 'backgroundColor', '#ececec');
          break;
        }
      }
    }
    

The above code will iterate through the cells of the specified row and check if the col.id matches the provided fieldName + rowIndex. If a match is found, the Renderer2 is used to set the background color of the cell to #ececec.

Note: Make sure to import the necessary dependencies such as Renderer2 and ElementRef in your component file.

There is an event called onEditComplete in the editable table component that you can utilize by adding certain properties to the <td> tag, as mentioned in the documentation. Here's an example:

<td [pEditableColumn]="rowData"
[pEditableColumnField]="'year'" [pEditableColumnRowIndex]="index"> 

In the example above, rowData corresponds to the product in our case, and 'year' represents the property of the product that this column is associated with. The columnsRowIndex property is set to the index value in our example.

However, it's important to note that the onEditComplete event fires only when the input field loses focus (on blur). This means it won't notify you immediately if the data in the field changes without triggering the blur event.

If you require real-time updates or want to track changes as the user types, you'll need to use other mechanisms, such as (ngModelChange) or (input) events, as shown in the previous code example.

There might be alternative solutions available, but this approach should effectively address your requirements.