Emphasize cells and headers when a cell's value deviates from its initial value

I implemented cell editing in my primeng table. Here is the code:

<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

The cell edit feature works perfectly. I wish to visually highlight cells and headers in red when a cell's value is changed from its original value. How can I achieve this?

Answer №1

To add color to the modified cell in your component's HTML, you can follow these steps:

  1. Include a template reference variable #rows in the <tr> element to access the rows using @ViewChildren. This allows you to interact with the rows in your component.

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

    <td pEditableColumn [id]="'name' + ri">
    
  3. Incorporate (ngModelChange) within the <input> element representing the editable field to detect changes in the input value. Upon value change, call a method like

    colorizeEditedCell(rowIndex, fieldName)
    passing the rowIndex and fieldName as arguments.

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

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

    constructor(private _renderer2: Renderer2) {}
    
  6. Define the function colorizeEditedCell within your component to set the background color of the edited cell. This function receives 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 provided code will iterate through the cells of the specified row and compare the col.id with the given fieldName + rowIndex. Upon finding a match, the Renderer2 sets the background color of the cell to #ececec.

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

An event named onEditComplete is present in the editable table component which you can use by setting certain properties on the <td> tag, as explained in the documentation. Here’s an example:

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

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

However, note that the onEditComplete event triggers only when the input field loses focus (on blur). Thus, it won’t immediately notify about data changes without blur event activation.

If real-time updates or continuous tracking during user input are needed, alternative mechanisms like (ngModelChange) or (input) events must be utilized, as demonstrated in the previous code snippet.

Alternate solutions may exist, but this proposed method should effectively meet your needs.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Infinite layers of options in the dropdown navigation bar

I am facing an issue with a dynamically generated unordered list that I want to turn into a dropdown menu. The challenge is that I do not know how many levels there will be, and I only want to display one level at a time. Here is what I have tried so far ...

Controlling File Upload Edits: A Guide to Effective Management

I am facing an issue on my product page related to adding and updating products in the database. The problem lies with images not displaying correctly. During the product insertion process, everything works fine. In my aspx page, I have the following code ...

Modify th:hover in CSS to alter the background color

I currently have a table structured as follows: <table class="cedvel"> <caption> count: <%:Html.Encode(TempData["RowsCount"])%></caption> <thead> <tr&g ...

Arranging an array containing three elements

As I work on my angular app, I have come across the following array: [ { "Name": "Jack", "IncomingTime": "2020-06-19T11:02+00:00", "Outgoingtime": "2020-06-19T11:07+00:00" ...

Show full-screen images on click using Ionic framework

Currently, I am working on developing a mobile app using the Ionic framework. I have created a layout that resembles the one shown in this Card Layout. My question is: How can I make the card image display in full screen when clicked by the user and retur ...

Angular is facing a challenge in locating the main parent based on its class interface

After reading the angular documentation here, I implemented a Parent class like this: export abstract class Parent {} In the AlexComponent, I set this component as the Parent for its children with the following code: providers: [{ provide: Parent, useExis ...

What is the method in PHP to send an HTML file along with a value in response to a POST request?

I have a PHP file where I want to include a dropdown list and submit button. The dropdown list should display filenames for the user to choose from. Once the user selects a filename from the dropdown list and clicks the submit button, the PHP file should r ...

Ways to decrease the space between lines of text within a single mat-option element

::ng-deep .mat-select-panel mat-option.mat-option { height: unset; } ::ng-deep .mat-option-text.mat-option-text { white-space: normal; } Currently, I have implemented this code to ensure that text in options wraps to the next line when it's too ...

Is there a way to hide my jQuery menu?

Can anyone help me figure out how to make it close when I click on a link? <nav class="navigation"> <a href="" class="menuIcon"><i class="fa fa-bars"></i></a> <ul class="nav"> <li class="clearfix"&g ...

Supply a variety of contexts to ngIf

Consider this template example. I am creating a user context using the as syntax and want to pass it into the userTmpl. It seems like there is no direct way to pass context beyond what is specified in the ngIf condition, which in this case is the showUser ...

"I am seeking a solution to seamlessly link the frontend and backend in order to effortlessly transfer objects from the frontend

Looking at the code snippet below, I have defined the following ngOnInit() for testing purposes: ngOnInit(): void { this.http.post<any>('http://localhost:8080/api/answers', { title: 'Angular POST Request Example' }); } Addi ...

Tips for showcasing the contents of a file on a website

Greetings! I am a newcomer to the world of web development and I am seeking a method to showcase file content on a webpage. Presently, I have succeeded in loading text file content and displaying it in a large text box. However, I am now interested in di ...

Tips for linking two project routes in NodeJS and incorporating React (I am interested in invoking React within the NodeJS project)

I'm in the process of linking two projects, one using reactJS and the other NodeJS. Currently, NodeJS is running smoothly on localhost:3000. Next, I want to call a React application which redirects to port localhost:3001. How can I seamlessly connect ...

Could I potentially pause and wait for a subscription in Angular?

I'm looking to display a list of posts similar to this: Post List In order to indicate which post is favorited by a user, I need to retrieve data from two different collections in my MongoDB database. The ngOnInit function in my post-list.component.t ...

Updating Angular components by consolidating multiple inputs and outputs into a unified configuration object

When I develop components, they often begin with numerous @Input and @Output properties. However, as I continue to add more properties, I find it beneficial to transition to utilizing a single config object as the input. For instance, consider a component ...

Utilizing intricate nested loops in Angular.JS for maximum efficiency and functionality

Struggling to work with data looping in Angular.JS, especially when it comes to specific formatting Let's illustrate what I'm aiming for using Java Here's a snippet: int itemCount = 0; for(int i = 0; i < JSON.length(); i = i + 3) { ...

What is the best way to conceal a dropdown menu when the page first loads?

I have a dropdown menu that is displaying like this: <ul> <li class="dropdown open"> <a aria-expanded="true" href="#" class="dropdown-toggle waves-effect waves-button waves-classic" data-toggle="dropdown"> <spa ...

Issue with jQuery: Changes are not being triggered and clicks are also not working

I managed to recreate the modifications of my complex script in a simple jsfiddle, which can be found here. Below is the code I am working with locally: HTML <input type="text" id="rangeStart" value="updateMe" /><br/> <input type="text" c ...

Iterate through an Array of Objects and exhibit a single object property in HTML one at a time by utilizing Javascript

I am working with an array of objects that contain two properties: "quote" and "author". I have a container div where I want the quotes to be displayed one by one at an interval of every 2 seconds. Currently, it is showing one letter at a time instead of d ...

What happens when dynamically loaded static resources are loaded?

Currently, I am dynamically injecting HTML into a page using JQuery AJAX. The injected HTML contains script and link tags for JS and CSS files respectively. The issue I am facing is that my initPage() function runs before the script containing its definiti ...