Conditional Formatting
Style rows and cells from your data without templates: class hooks, declarative formatting rules, data bars, colour scales and icon sets. Every visual is a design-token class or a CSS custom property, so themes, dark mode and Windows High Contrast keep working.
Class hooks & formatting rules
rowClass / cellClass return a string, an array or a { class: condition } record. A column's conditionalFormats mixes rules (when as a predicate or an { operator, value } condition, painted with a token tone / background) with a data bar and an icon set relative to the rendered rows. cellPrepared hands over the element for anything else.
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { OgeColumn, OgeGrid } from '@oge-ui/grid';
import type { OgeCellPreparedEvent, OgeConditionalFormat, OgeGridColumnInfo } from '@oge-ui/grid';
interface Employee {
id: number;
firstName: string;
department: string;
salary: number;
}
@Component({
selector: 'demo-root',
imports: [OgeColumn, OgeGrid],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<oge-grid [data]="employees" keyField="id"
[rowClass]="rowClass" [cellClass]="cellClass"
(cellPrepared)="onCellPrepared($event)">
<oge-column field="firstName" caption="Name" />
<oge-column field="department" caption="Department" />
<!-- token-only formats: rule classes, a data bar, an icon set -->
<oge-column field="salary" caption="Salary" dataType="number"
[conditionalFormats]="salaryFormats" />
</oge-grid>
`,
})
export class Demo {
readonly employees = [
{ id: 1, firstName: 'Ali', lastName: 'Yılmaz', department: 'Engineering', city: 'İstanbul', salary: 8400, hireDate: '2019-03-11' },
{ id: 2, firstName: 'Ayşe', lastName: 'Kaya', department: 'Sales', city: 'Ankara', salary: 7200, hireDate: '2020-07-02' },
{ id: 3, firstName: 'Mehmet', lastName: 'Demir', department: 'Engineering', city: 'İzmir', salary: 9100, hireDate: '2018-01-23' },
{ id: 4, firstName: 'Zeynep', lastName: 'Şahin', department: 'Finance', city: 'İstanbul', salary: 6800, hireDate: '2021-11-15' },
{ id: 5, firstName: 'Emre', lastName: 'Çelik', department: 'Support', city: 'Bursa', salary: 5400, hireDate: '2022-05-09' },
];
protected readonly rowClass = (row: Employee) => ({
'is-engineering': row.department === 'Engineering',
});
protected readonly cellClass = (row: Employee, column: OgeGridColumnInfo) =>
column.field === 'firstName' && row.salary > 8500 ? 'is-top-earner' : null;
protected readonly salaryFormats: OgeConditionalFormat<Employee>[] = [
{ when: { operator: 'ge', value: 9000 }, style: { tone: 'success', bold: true } },
{ when: (value) => (value as number) < 6000, style: { background: 'danger' } },
{ type: 'dataBar' },
{ type: 'iconSet', icons: 'arrows' },
];
protected onCellPrepared(event: OgeCellPreparedEvent<Employee>): void {
// the imperative escape hatch: decorate the element itself
if (event.field === 'salary') event.element.title = String(event.value);
}
}Merged cells, spans, auto-fit & hints
mergeCells merges equal adjacent values into one cell with aria-rowspan; cellSpan returns { rowSpan, colSpan } per cell. The arrow keys step over a merged area. columnAutoWidth sizes the columns to their content (double-click a resize handle, or use the header menu's Size to fit, for one column), and cellHintEnabled shows truncated text in a tooltip on hover and on keyboard focus.
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { OgeColumn, OgeGrid } from '@oge-ui/grid';
import type { OgeGridColumnInfo } from '@oge-ui/grid';
interface Employee {
id: number;
department: string;
city: string;
}
@Component({
selector: 'demo-root',
imports: [OgeColumn, OgeGrid],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<!-- equal adjacent values merge (aria-rowspan); cellSpan spans columns -->
<oge-grid [data]="employees" keyField="id" [cellSpan]="cellSpan"
[cellHintEnabled]="true">
<oge-column field="department" caption="Department" [mergeCells]="true" />
<!-- a narrow column: hover or focus a city for the full text,
double-click its resize handle to fit it -->
<oge-column field="city" caption="City" [width]="64" />
<oge-column field="firstName" caption="First name" />
<oge-column field="lastName" caption="Last name" />
</oge-grid>
`,
})
export class Demo {
readonly employees = [
{ id: 1, firstName: 'Ali', lastName: 'Yılmaz', department: 'Engineering', city: 'İstanbul', salary: 8400, hireDate: '2019-03-11' },
{ id: 2, firstName: 'Ayşe', lastName: 'Kaya', department: 'Sales', city: 'Ankara', salary: 7200, hireDate: '2020-07-02' },
{ id: 3, firstName: 'Mehmet', lastName: 'Demir', department: 'Engineering', city: 'İzmir', salary: 9100, hireDate: '2018-01-23' },
{ id: 4, firstName: 'Zeynep', lastName: 'Şahin', department: 'Finance', city: 'İstanbul', salary: 6800, hireDate: '2021-11-15' },
{ id: 5, firstName: 'Emre', lastName: 'Çelik', department: 'Support', city: 'Bursa', salary: 5400, hireDate: '2022-05-09' },
];
protected readonly cellSpan = (row: Employee, column: OgeGridColumnInfo) =>
column.field === 'firstName' && row.id === 1 ? { colSpan: 2 } : null;
}Notes
- Data bars and colour scales are relative to the column's numeric range over the rendered rows unless
min/maxare given; icon sets split that range in thirds unlessthresholdsare given. - Spans never cross group rows and are not applied while the grid is virtualized; row spans assume uniform row heights.