Conditional Styling

The FlexGrid provides a powerful infrastructure for binding cells to data and formatting the cells using CSS. But in some cases that may not be enough. In those situations, use the formatItem event to customize the style or the content presented in each cell. The grid below uses formatItem to calculate and format cells that show the difference between values in the current and previous items:

import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './styles.css'; import { Globalize } from '@grapecity/wijmo'; import { FlexGrid, Row, AllowMerging } from '@grapecity/wijmo.grid'; document.readyState === 'complete' ? init() : window.onload = init; function init() { // generate some random data var countries = 'US,Germany,UK,Japan,Italy,Greece'.split(','), data = []; for (var i = 0; i < 200; i++) { data.push({ id: i, country: countries[i % countries.length], sales: Math.random() * 10000, expenses: Math.random() * 5000, }); } // show data in a grid var theGrid = new FlexGrid('#theGrid', { isReadOnly: true, allowResizing: 'None', allowDragging: 'None', allowSorting: false, selectionMode: 'RowRange', alternatingRowStep: 0, autoGenerateColumns: false, columns: [ { binding: 'id', header: 'ID', width: 50 }, { binding: 'country', header: 'Country' }, { binding: 'sales', header: 'Sales', width: 80, format: 'n0' }, { binding: 'salesDiff', header: 'Diff', dataType: 'Number', width: 80, format: 'p0' }, { binding: 'expenses', header: 'Expenses', width: 80, format: 'n0' }, { binding: 'expensesDiff', header: 'Diff', dataType: 'Number', width: 80, format: 'p0' } ], itemsSource: data, }); // insert extra column header row var ch = theGrid.columnHeaders, hr = new Row(); ch.rows.insert(0, hr); // fill out headings in extra header row for (var i = 0; i < theGrid.columns.length; i++) { var hdr = ch.getCellData(1, i, false); if (hdr == 'Diff') hdr = ch.getCellData(1, i - 1, false); ch.setCellData(0, i, hdr); } // allow merging across and down extra header row theGrid.allowMerging = AllowMerging.ColumnHeaders; hr.allowMerging = true; theGrid.columns[0].allowMerging = true; theGrid.columns[1].allowMerging = true; // custom rendering for headers and "Diff" columns theGrid.formatItem.addHandler(function (s, e) { // center-align column headers if (e.panel == s.columnHeaders) { e.cell.innerHTML = '<div class="v-center">' + e.cell.innerHTML + '</div>'; } // custom rendering for "Diff" columns if (e.panel == s.cells) { var col = s.columns[e.col]; if (e.row > 0 && (col.binding == 'salesDiff' || col.binding == 'expensesDiff')) { var vnow = s.getCellData(e.row, e.col - 1), vprev = s.getCellData(e.row - 1, e.col - 1), diff = (vnow / vprev) - 1; // format the cell var html = '<div class="diff-{cls}">' + '<span style="font-size:75%">{val}</span> ' + '<span style="font-size:120%" class="wj-glyph-{glyph}"></span>'; html = html.replace('{val}', Globalize.format(diff, col.format)); if (diff < 0.01) { html = html.replace('{cls}', 'down').replace('{glyph}', 'down'); } else if (diff > 0.01) { html = html.replace('{cls}', 'up').replace('{glyph}', 'up'); } else { html = html.replace('{cls}', 'none').replace('{glyph}', 'circle'); } e.cell.innerHTML = html; } } }); } <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>GrapeCity Wijmo FlexGrid Conditional Styling</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: 250px; margin: 10px 0; } .wj-cell .v-center { position: relative; top: 50%; transform: translateY(-50%); white-space: pre-wrap; } .wj-cell:not(.wj-state-selected):not(.wj-state-multi-selected) .diff-none { color: #d8b400; } .wj-cell:not(.wj-state-selected):not(.wj-state-multi-selected) .diff-up { color: #4c8f00; } .wj-cell:not(.wj-state-selected):not(.wj-state-multi-selected) .diff-down { color: #9f0000; } body { margin-bottom: 20px; } import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './styles.css'; // import { Component, enableProdMode, NgModule } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { BrowserModule } from '@angular/platform-browser'; import * as wjcCore from '@grapecity/wijmo'; import * as wjcGrid from '@grapecity/wijmo.grid'; import { WjGridModule } from '@grapecity/wijmo.angular2.grid'; // @Component({ selector: 'app-component', templateUrl: 'src/app.component.html' }) export class AppComponent { data: any[]; // DataSvc will be passed by derived classes constructor() { this.data = this._getData(); } initializeGrid(flex: wjcGrid.FlexGrid) { // insert extra column header row let ch = flex.columnHeaders, hr = new wjcGrid.Row(); ch.rows.insert(0, hr); // fill out headings in extra header row for (let i = 0; i < flex.columns.length; i++) { let hdr = ch.getCellData(1, i, false); if (hdr == 'Diff') { hdr = ch.getCellData(1, i - 1, false); } ch.setCellData(0, i, hdr); } // allow merging across and down extra header row flex.allowMerging = wjcGrid.AllowMerging.ColumnHeaders; hr.allowMerging = true; flex.columns[0].allowMerging = true; flex.columns[1].allowMerging = true; // custom rendering for headers and "Diff" columns flex.formatItem.addHandler((s: any, e: wjcGrid.FormatItemEventArgs) => { // center-align column headers if (e.panel == s.columnHeaders) { e.cell.innerHTML = '<div class="v-center">' + e.cell.innerHTML + '</div>'; } // custom rendering for "Diff" columns if (e.panel == s.cells) { let col = s.columns[e.col]; if (e.row > 0 && (col.binding == 'salesDiff' || col.binding == 'expensesDiff')) { let vnow = s.getCellData(e.row, e.col - 1), vprev = s.getCellData(e.row - 1, e.col - 1), diff = (vnow / vprev) - 1; // format the cell let html = '<div class="diff-{cls}">' + '<span style="font-size:75%">{val}</span> ' + '<span style="font-size:120%" class="wj-glyph-{glyph}"></span>'; html = html.replace('{val}', wjcCore.Globalize.format(diff, col.format)); if (diff < 0.01) { html = html.replace('{cls}', 'down').replace('{glyph}', 'down'); } else if (diff > 0.01) { html = html.replace('{cls}', 'up').replace('{glyph}', 'up'); } else { html = html.replace('{cls}', 'none').replace('{glyph}', 'circle'); } e.cell.innerHTML = html; } } }); } private _getData() { // generate some random data let countries = 'US,Germany,UK,Japan,Italy,Greece'.split(','), data = []; for (let i = 0; i < 200; i++) { data.push({ id: i, country: countries[i % countries.length], sales: Math.random() * 10000, expenses: Math.random() * 5000 }); } return data; } } // @NgModule({ imports: [WjGridModule, BrowserModule], declarations: [AppComponent], bootstrap: [AppComponent] }) export class AppModule { } // enableProdMode(); // Bootstrap application with hash style navigation and global services. platformBrowserDynamic().bootstrapModule(AppModule); <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>GrapeCity Wijmo FlexGrid Conditional Styling</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Polyfills --> <script src="node_modules/core-js/client/shim.min.js"></script> <script src="node_modules/zone.js/dist/zone.min.js"></script> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.js"></script> <script src="systemjs.config.js"></script> <script> // workaround to load 'rxjs/operators' from the rxjs bundle System.import('rxjs').then(function (m) { System.set(SystemJS.resolveSync('rxjs/operators'), System.newModule(m.operators)); System.import('./src/app.component'); }); </script> </head> <body> <app-component></app-component> </body> </html> <div class="container-fluid"> <wj-flex-grid #flex [isReadOnly]="true" [allowResizing]="'None'" [allowDragging]="'None'" [allowSorting]="false" [selectionMode]="'RowRange'" [alternatingRowStep]="0" (initialized)="initializeGrid(flex)" [(itemsSource)]="data"> <wj-flex-grid-column [binding]="'id'" [header]="'ID'" [width]="50"></wj-flex-grid-column> <wj-flex-grid-column [binding]="'country'" [header]="'Country'"></wj-flex-grid-column> <wj-flex-grid-column [binding]="'sales'" [header]="'Sales'" [width]="80" [format]="'n0'"></wj-flex-grid-column> <wj-flex-grid-column [binding]="'salesDiff'" [header]="'Diff'" [dataType]="'Number'" [width]="80" [format]="'p0'"></wj-flex-grid-column> <wj-flex-grid-column [binding]="'expenses'" [header]="'Expenses'" [width]="80" [format]="'n0'"></wj-flex-grid-column> <wj-flex-grid-column [binding]="'expensesDiff'" [header]="'Diff'" [dataType]="'Number'" [width]="80" [format]="'p0'"></wj-flex-grid-column> </wj-flex-grid> </div> .wj-flexgrid { max-height: 250px; margin: 10px 0; } .wj-cell .v-center { position: relative; top: 50%; transform: translateY(-50%); white-space: pre-wrap; } .wj-cell:not(.wj-state-selected):not(.wj-state-multi-selected) .diff-none { color: #d8b400; } .wj-cell:not(.wj-state-selected):not(.wj-state-multi-selected) .diff-up { color: #4c8f00; } .wj-cell:not(.wj-state-selected):not(.wj-state-multi-selected) .diff-down { color: #9f0000; } body { margin-bottom: 20px; } <template> <div class="container-fluid"> <wj-flex-grid :isReadOnly="true" :allowResizing="'None'" :allowDragging="'None'" :allowSorting="false" :selectionMode="'RowRange'" :alternatingRowStep="0" :initialized="initializeGrid" :itemsSource="data" > <wj-flex-grid-column :binding="'id'" :header="'ID'" :width="50"></wj-flex-grid-column> <wj-flex-grid-column :binding="'country'" :header="'Country'"></wj-flex-grid-column> <wj-flex-grid-column :binding="'sales'" :header="'Sales'" :width="80" :format="'n0'"></wj-flex-grid-column> <wj-flex-grid-column :binding="'salesDiff'" :header="'Diff'" :dataType="'Number'" :width="80" :format="'p0'" ></wj-flex-grid-column> <wj-flex-grid-column :binding="'expenses'" :header="'Expenses'" :width="80" :format="'n0'" ></wj-flex-grid-column> <wj-flex-grid-column :binding="'expensesDiff'" :header="'Diff'" :dataType="'Number'" :width="80" :format="'p0'" ></wj-flex-grid-column> </wj-flex-grid> </div> </template> <script> import "@grapecity/wijmo.styles/wijmo.css"; import "bootstrap.css"; import Vue from "vue"; import "@grapecity/wijmo.vue2.grid"; import * as wjcCore from "@grapecity/wijmo"; import * as wjcGrid from "@grapecity/wijmo.grid"; let App = Vue.extend({ name: "app", data: function() { return { data: this._getData() }; }, methods: { initializeGrid(flex) { // insert extra column header row let ch = flex.columnHeaders, hr = new wjcGrid.Row(); ch.rows.insert(0, hr); // fill out headings in extra header row for (let i = 0; i < flex.columns.length; i++) { let hdr = ch.getCellData(1, i, false); if (hdr == "Diff") { hdr = ch.getCellData(1, i - 1, false); } ch.setCellData(0, i, hdr); } // allow merging across and down extra header row flex.allowMerging = wjcGrid.AllowMerging.ColumnHeaders; hr.allowMerging = true; flex.columns[0].allowMerging = true; flex.columns[1].allowMerging = true; // custom rendering for headers and "Diff" columns flex.formatItem.addHandler((s, e) => { // center-align column headers if (e.panel == s.columnHeaders) { e.cell.innerHTML = '<div class="v-center">' + e.cell.innerHTML + "</div>"; } // custom rendering for "Diff" columns if (e.panel == s.cells) { let col = s.columns[e.col]; if ( e.row > 0 && (col.binding == "salesDiff" || col.binding == "expensesDiff") ) { let vnow = s.getCellData(e.row, e.col - 1), vprev = s.getCellData(e.row - 1, e.col - 1), diff = vnow / vprev - 1; // format the cell let html = '<div class="diff-{cls}">' + '<span style="font-size:75%">{val}</span> ' + '<span style="font-size:120%" class="wj-glyph-{glyph}"></span>'; html = html.replace( "{val}", wjcCore.Globalize.format(diff, col.format) ); if (diff < 0.01) { html = html .replace("{cls}", "down") .replace("{glyph}", "down"); } else if (diff > 0.01) { html = html .replace("{cls}", "up") .replace("{glyph}", "up"); } else { html = html .replace("{cls}", "none") .replace("{glyph}", "circle"); } e.cell.innerHTML = html; } } }); }, _getData: function() { // generate some random data let countries = "US,Germany,UK,Japan,Italy,Greece".split(","), data = []; for (let i = 0; i < 200; i++) { data.push({ id: i, country: countries[i % countries.length], sales: Math.random() * 10000, expenses: Math.random() * 5000 }); } return data; } } }); new Vue({ render: h => h(App) }).$mount("#app"); </script> <style> .wj-flexgrid { max-height: 250px; margin: 10px 0; } .wj-cell .v-center { position: relative; top: 50%; transform: translateY(-50%); white-space: pre-wrap; } .wj-cell:not(.wj-state-selected):not(.wj-state-multi-selected) .diff-none { color: #d8b400; } .wj-cell:not(.wj-state-selected):not(.wj-state-multi-selected) .diff-up { color: #4c8f00; } .wj-cell:not(.wj-state-selected):not(.wj-state-multi-selected) .diff-down { color: #9f0000; } body { margin-bottom: 20px; } </style> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>AutoComplete</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.vue'); </script> </head> <body> <div id="app"> </div> </body> </html> import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './app.css'; import * as React from 'react'; import * as ReactDOM from 'react-dom'; import * as wjFlexGrid from '@grapecity/wijmo.react.grid'; import * as wjcCore from '@grapecity/wijmo'; import * as wjcGrid from '@grapecity/wijmo.grid'; class App extends React.Component { constructor(props) { super(props); this.state = { data: this._getData(200) }; } render() { return <div className="container-fluid"> <wjFlexGrid.FlexGrid isReadOnly={true} allowResizing="None" allowDragging="None" allowSorting={false} selectionMode="RowRange" alternatingRowStep={0} initialized={this.initializeGrid} itemsSource={this.state.data}> <wjFlexGrid.FlexGridColumn binding="id" header="ID" width={50}></wjFlexGrid.FlexGridColumn> <wjFlexGrid.FlexGridColumn binding="country" header="Country"></wjFlexGrid.FlexGridColumn> <wjFlexGrid.FlexGridColumn binding="sales" header="Sales" width={80} format="n0"> </wjFlexGrid.FlexGridColumn> <wjFlexGrid.FlexGridColumn binding="salesDiff" header="Diff" dataType="Number" width={80} format="p0"> </wjFlexGrid.FlexGridColumn> <wjFlexGrid.FlexGridColumn binding="expenses" header="Expenses" width={80} format="n0"> </wjFlexGrid.FlexGridColumn> <wjFlexGrid.FlexGridColumn binding="expensesDiff" header="Diff" dataType="Number" width={80} format="p0"> </wjFlexGrid.FlexGridColumn> </wjFlexGrid.FlexGrid> </div>; } initializeGrid(flex) { // insert extra column header row let ch = flex.columnHeaders, hr = new wjcGrid.Row(); ch.rows.insert(0, hr); // fill out headings in extra header row for (let i = 0; i < flex.columns.length; i++) { let hdr = ch.getCellData(1, i, false); if (hdr == 'Diff') { hdr = ch.getCellData(1, i - 1, false); } ch.setCellData(0, i, hdr); } // allow merging across and down extra header row flex.allowMerging = wjcGrid.AllowMerging.ColumnHeaders; hr.allowMerging = true; flex.columns[0].allowMerging = true; flex.columns[1].allowMerging = true; // custom rendering for headers and "Diff" columns flex.formatItem.addHandler((s, e) => { // center-align column headers if (e.panel == s.columnHeaders) { e.cell.innerHTML = '<div class="v-center">' + e.cell.innerHTML + '</div>'; } // custom rendering for "Diff" columns if (e.panel == s.cells) { let col = s.columns[e.col]; if (e.row > 0 && (col.binding == 'salesDiff' || col.binding == 'expensesDiff')) { let vnow = s.getCellData(e.row, e.col - 1), vprev = s.getCellData(e.row - 1, e.col - 1), diff = (vnow / vprev) - 1; // format the cell let html = '<div class="diff-{cls}">' + '<span style="font-size:75%">{val}</span> ' + '<span style="font-size:120%" class="wj-glyph-{glyph}"></span>'; html = html.replace('{val}', wjcCore.Globalize.format(diff, col.format)); if (diff < 0.01) { html = html.replace('{cls}', 'down').replace('{glyph}', 'down'); } else if (diff > 0.01) { html = html.replace('{cls}', 'up').replace('{glyph}', 'up'); } else { html = html.replace('{cls}', 'none').replace('{glyph}', 'circle'); } e.cell.innerHTML = html; } } }); } _getData(cnt) { // generate some random data let countries = 'US,Germany,UK,Japan,Italy,Greece'.split(','), data = []; for (let i = 0; i < 200; i++) { data.push({ id: i, country: countries[i % countries.length], sales: Math.random() * 10000, expenses: Math.random() * 5000 }); } return data; } } ReactDOM.render(<App />, document.getElementById('app')); <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>GrapeCity Wijmo FlexGrid Conditional Styling</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 id="app"></div> </body> </html> .wj-flexgrid { max-height: 250px; margin: 10px 0; } .wj-cell .v-center { position: relative; top: 50%; transform: translateY(-50%); white-space: pre-wrap; } .wj-cell:not(.wj-state-selected):not(.wj-state-multi-selected) .diff-none { color: #d8b400; } .wj-cell:not(.wj-state-selected):not(.wj-state-multi-selected) .diff-up { color: #4c8f00; } .wj-cell:not(.wj-state-selected):not(.wj-state-multi-selected) .diff-down { color: #9f0000; } body { margin-bottom: 20px; }