Highlight Edits

This sample shows how you can highlight cells that have been edited.

The sample uses an EditHighlighter class that keeps track of the original values for cells that have been edited or pasted, and highlights them by applying a custom CSS class to the cells.

If you restore a cell's original value, the highlight is removed.

Learn about FlexGrid | FlexGrid API Reference

import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './styles.css'; import { FlexGrid } from '@grapecity/wijmo.grid'; import { EditHighlighter } from './edit-highlighter'; document.readyState === 'complete' ? init() : window.onload = init; function init() { // create the grid var theGrid = new FlexGrid('#theGrid', { itemsSource: getData() }); // create the EditHighlighter new EditHighlighter(theGrid, 'cell-changed'); // create some random data function getData() { var data = []; var countries = 'US,Germany,UK,Japan,Italy,Greece'.split(','); for (var i = 0; i < countries.length; i++) { data.push({ id: i, country: countries[i], sales: Math.random() * 10000, expenses: Math.random() * 5000, overdue: i % 4 == 0 }); } return data; } }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>MESCIUS Wijmo FlexGrid Editing</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app'); </script> </head> <body> <div class="container-fluid"> <div id="theGrid"></div> </div> </body> </html>
.wj-flexgrid { max-height: 220px; margin: 10px; } .wj-flexgrid .cell-changed { background-color: lightpink; } body { margin-bottom: 24px; }
import { isUndefined, isDate, toggleClass } from '@grapecity/wijmo'; /** * Class that highlights cells that have been edited in a FlexGrid. */ export class EditHighlighter { /** * Initializes a new instance of the {@link EditHighlighter} class. * * @param grid FlexGrid to highlight. * @param cssClass Class name to apply to changed cells. */ constructor(grid, cssClass) { this._originalValues = new Map(); this._grid = grid; let cellChanging = this._cellChanging.bind(this), cellChanged = this._cellChanged.bind(this); grid.beginningEdit.addHandler(cellChanging); grid.cellEditEnded.addHandler(cellChanged); grid.pastingCell.addHandler(cellChanging); grid.pastedCell.addHandler(cellChanged); grid.formatItem.addHandler((s, e) => { if (e.panel == s.cells) { let changed = this._hasChange(e.getRow().dataItem, e.getColumn().binding); toggleClass(e.cell, 'cell-changed', changed); } }); } /** * Clears all the changes and removes all highlights. */ clearChanges() { this._originalValues.clear(); this._grid.invalidate(); } // checks whether a cell has changed _hasChange(item, binding) { item = this._originalValues.get(item); return item != null && !isUndefined(item[binding]); } // handles cell changing (edit or paste) _cellChanging(s, e) { this._originalValue = s.getCellData(e.row, e.col, false); } // handles cell changed (edit or paste) _cellChanged(s, e) { let newValue = s.getCellData(e.row, e.col, false); this._storeChange(e.getRow().dataItem, e.getColumn().binding, this._originalValue, newValue); } // store a change into the _originalValues map _storeChange(item, binding, originalValue, newValue) { // get the item with the original values let editItem = this._originalValues.get(item); if (editItem == null) { editItem = {}; this._originalValues.set(item, editItem); } // get the original value from the item if possible let editValue = editItem[binding]; if (!isUndefined(editValue)) { originalValue = editValue; } // store or clear the change if (this._sameValue(originalValue, newValue)) { delete editItem[binding]; if (Object.keys(editItem).length == 0) { this._originalValues.delete(item); } } else { editItem[binding] = originalValue; } } // compare two values taking dates into account _sameValue(item1, item2) { if (item1 === item2) { return true; } if (isDate(item1) && isDate(item2)) { return item1.getTime() == item2.getTime(); } return false; } }
(function (global) { System.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true }, meta: { '*.css': { loader: 'css' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { 'jszip': 'npm:jszip/dist/jszip.js', '@grapecity/wijmo': 'npm:@grapecity/wijmo/index.js', '@grapecity/wijmo.input': 'npm:@grapecity/wijmo.input/index.js', '@grapecity/wijmo.styles': 'npm:@grapecity/wijmo.styles', '@grapecity/wijmo.cultures': 'npm:@grapecity/wijmo.cultures', '@grapecity/wijmo.chart': 'npm:@grapecity/wijmo.chart/index.js', '@grapecity/wijmo.chart.analytics': 'npm:@grapecity/wijmo.chart.analytics/index.js', '@grapecity/wijmo.chart.animation': 'npm:@grapecity/wijmo.chart.animation/index.js', '@grapecity/wijmo.chart.annotation': 'npm:@grapecity/wijmo.chart.annotation/index.js', '@grapecity/wijmo.chart.finance': 'npm:@grapecity/wijmo.chart.finance/index.js', '@grapecity/wijmo.chart.finance.analytics': 'npm:@grapecity/wijmo.chart.finance.analytics/index.js', '@grapecity/wijmo.chart.hierarchical': 'npm:@grapecity/wijmo.chart.hierarchical/index.js', '@grapecity/wijmo.chart.interaction': 'npm:@grapecity/wijmo.chart.interaction/index.js', '@grapecity/wijmo.chart.radar': 'npm:@grapecity/wijmo.chart.radar/index.js', '@grapecity/wijmo.chart.render': 'npm:@grapecity/wijmo.chart.render/index.js', '@grapecity/wijmo.chart.webgl': 'npm:@grapecity/wijmo.chart.webgl/index.js', '@grapecity/wijmo.chart.map': 'npm:@grapecity/wijmo.chart.map/index.js', '@grapecity/wijmo.gauge': 'npm:@grapecity/wijmo.gauge/index.js', '@grapecity/wijmo.grid': 'npm:@grapecity/wijmo.grid/index.js', '@grapecity/wijmo.grid.detail': 'npm:@grapecity/wijmo.grid.detail/index.js', '@grapecity/wijmo.grid.filter': 'npm:@grapecity/wijmo.grid.filter/index.js', '@grapecity/wijmo.grid.search': 'npm:@grapecity/wijmo.grid.search/index.js', '@grapecity/wijmo.grid.grouppanel': 'npm:@grapecity/wijmo.grid.grouppanel/index.js', '@grapecity/wijmo.grid.multirow': 'npm:@grapecity/wijmo.grid.multirow/index.js', '@grapecity/wijmo.grid.transposed': 'npm:@grapecity/wijmo.grid.transposed/index.js', '@grapecity/wijmo.grid.transposedmultirow': 'npm:@grapecity/wijmo.grid.transposedmultirow/index.js', '@grapecity/wijmo.grid.pdf': 'npm:@grapecity/wijmo.grid.pdf/index.js', '@grapecity/wijmo.grid.sheet': 'npm:@grapecity/wijmo.grid.sheet/index.js', '@grapecity/wijmo.grid.xlsx': 'npm:@grapecity/wijmo.grid.xlsx/index.js', '@grapecity/wijmo.grid.selector': 'npm:@grapecity/wijmo.grid.selector/index.js', '@grapecity/wijmo.grid.cellmaker': 'npm:@grapecity/wijmo.grid.cellmaker/index.js', '@grapecity/wijmo.nav': 'npm:@grapecity/wijmo.nav/index.js', '@grapecity/wijmo.odata': 'npm:@grapecity/wijmo.odata/index.js', '@grapecity/wijmo.olap': 'npm:@grapecity/wijmo.olap/index.js', '@grapecity/wijmo.rest': 'npm:@grapecity/wijmo.rest/index.js', '@grapecity/wijmo.pdf': 'npm:@grapecity/wijmo.pdf/index.js', '@grapecity/wijmo.pdf.security': 'npm:@grapecity/wijmo.pdf.security/index.js', '@grapecity/wijmo.viewer': 'npm:@grapecity/wijmo.viewer/index.js', '@grapecity/wijmo.xlsx': 'npm:@grapecity/wijmo.xlsx/index.js', '@grapecity/wijmo.undo': 'npm:@grapecity/wijmo.undo/index.js', '@grapecity/wijmo.interop.grid': 'npm:@grapecity/wijmo.interop.grid/index.js', '@grapecity/wijmo.touch': 'npm:@grapecity/wijmo.touch/index.js', '@grapecity/wijmo.cloud': 'npm:@grapecity/wijmo.cloud/index.js', '@grapecity/wijmo.barcode': 'npm:@grapecity/wijmo.barcode/index.js', '@grapecity/wijmo.barcode.common': 'npm:@grapecity/wijmo.barcode.common/index.js', '@grapecity/wijmo.barcode.composite': 'npm:@grapecity/wijmo.barcode.composite/index.js', '@grapecity/wijmo.barcode.specialized': 'npm:@grapecity/wijmo.barcode.specialized/index.js', 'jszip': 'npm:jszip/dist/jszip.js', 'bootstrap.css': 'npm:bootstrap/dist/css/bootstrap.min.css', 'css': 'npm:systemjs-plugin-css/css.js', 'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js', 'systemjs-babel-build':'npm:systemjs-plugin-babel/systemjs-babel-browser.js' }, // packages tells the System loader how to load when no filename and/or no extension packages: { src: { defaultExtension: 'js' }, "node_modules": { defaultExtension: 'js' }, } }); })(this);