Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions community-modules/locale/src/en-US.ts
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,7 @@ export const AG_GRID_LOCALE_EN = {
calculatedColumnExpressionAmbiguousReference:
'Ambiguous column reference "${variable}". Use the Columns list or a more specific group path.',
calculatedColumnExpressionUnknownReference: 'Unknown column reference "${variable}".',
calculatedColumnExpressionEmpty: 'Enter an expression.',
calculatedColumnApply: 'Apply',
calculatedColumnCancel: 'Cancel',

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { getInterfaceDocumentationModel } from '../utils/getInterfaceDocumentati
import { getOverrides } from '../utils/getOverrides';
import { getJsonFile } from '@utils/pages';
import CodeShiki from '@ag-website-shared/components/code/CodeShiki';
import { codeToHtml } from 'shiki';
import agDocsTheme from '@ag-website-shared/components/code/theme.json';
import { extractDecorations } from '@ag-website-shared/components/code/keepMarkup';

const { interfaceName, overrideSrc, names, exclude, config } = Astro.props;

Expand All @@ -23,11 +26,21 @@ const model = getInterfaceDocumentationModel({
codeLookup,
interfaceLookup,
});

let preHighlightedHtml: string | undefined;
if (model.type === 'code') {
const { cleanCode, decorations } = extractDecorations(model.code.trimEnd());
preHighlightedHtml = await codeToHtml(cleanCode, {
lang: 'typescript',
theme: agDocsTheme,
decorations,
} as any);
}
---

{
model.type === 'code' ? (
<CodeShiki code={model.code} keepMarkup={true} />
<CodeShiki code={model.code} preHighlightedHtml={preHighlightedHtml} />
) : (
<InterfaceDocumentation
client:load
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1406,24 +1406,6 @@
"url": "./calculated-columns/"
}
},
"addCalculatedColumn": {
"more": {
"name": "Calculated Columns API",
"url": "./calculated-columns/#api"
}
},
"updateCalculatedColumn": {
"more": {
"name": "Calculated Columns API",
"url": "./calculated-columns/#api"
}
},
"removeCalculatedColumn": {
"more": {
"name": "Calculated Columns API",
"url": "./calculated-columns/#api"
}
},
"openCalculatedColumnDialog": {
"more": {
"name": "Calculated Columns API",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const gridOptions: GridOptions<SalesRow> = {
columnDefs,
rowData,
calculatedColumns: {
columnHighlighting: true,
suppressColumnHighlighting: true,
},
defaultColDef: {
flex: 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import {
ValidationModule,
createGrid,
} from 'ag-grid-community';
import { CalculatedColumnsModule, RowGroupingModule } from 'ag-grid-enterprise';
import { CalculatedColumnsModule, ColumnMenuModule, RowGroupingModule } from 'ag-grid-enterprise';

ModuleRegistry.registerModules([
ClientSideRowModelModule,
CalculatedColumnsModule,
ColumnMenuModule,
RowGroupingModule,
NumberFilterModule,
...(process.env.NODE_ENV !== 'production' ? [ValidationModule] : []),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import {
ValidationModule,
createGrid,
} from 'ag-grid-community';
import { CalculatedColumnsModule } from 'ag-grid-enterprise';
import { CalculatedColumnsModule, ColumnMenuModule } from 'ag-grid-enterprise';

ModuleRegistry.registerModules([
ClientSideRowModelModule,
CalculatedColumnsModule,
ColumnMenuModule,
NumberEditorModule,
NumberFilterModule,
...(process.env.NODE_ENV !== 'production' ? [ValidationModule] : []),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Calculated Columns let you add read-only values to the grid without storing thos

## Enabling Calculated Columns

Calculated columns are enabled by registering `CalculatedColumnsModule` and setting `calculatedExpression` on a column definition. In source code and Grid API calls, bracket references such as `[revenue]` resolve to the same-row value from the column with that `colId`.
Calculated columns are enabled by registering `CalculatedColumnsModule` and setting `calculatedExpression` on a column definition. In source code, bracket references such as `[revenue]` resolve to the same-row value from the column with that `colId`.

```{% frameworkTransform=true %}
const gridOptions = {
Expand Down Expand Up @@ -110,23 +110,23 @@ This only controls the expression picker buttons. Use an empty array or `null` t

{% gridExampleRunner title="Dialog Expression Pickers" name="calculated-columns-dialog-helper-lists" exampleHeight=350 /%}

### columnHighlighting
### suppressColumnHighlighting

Use `columnHighlighting` to highlight the calculated column while its edit dialog is open:
Calculated columns are highlighted by default while their edit dialog is open. Use `suppressColumnHighlighting` to disable this highlight:

```{% frameworkTransform=true %}

const gridOptions = {
theme: myTheme,
calculatedColumns: {
columnHighlighting: true,
suppressColumnHighlighting: true,
},
};
```

When enabled, the highlighted header and cells highlight colour can also be customised with the `--ag-calculated-column-highlight-color` CSS variable.
When highlighting is not suppressed, the header and cells highlight colour can be customised with the `--ag-calculated-column-highlight-color` CSS variable.

{% gridExampleRunner title="Dialog Column Highlighting" name="calculated-columns-dialog-highlighting" exampleHeight=350 /%}
{% gridExampleRunner title="Suppress Dialog Column Highlighting" name="calculated-columns-dialog-highlighting" exampleHeight=350 /%}

## Advanced Calculated Columns

Expand Down Expand Up @@ -161,32 +161,40 @@ const gridOptions = {

Header cells and grid cells for calculated columns include the `ag-calculated-column` CSS class, which can be used for custom styling.

Calculated columns can also be managed from the Grid API. API-created columns are appended to the current column tree; use the column moving API afterwards if you need a specific display position. The original application-provided `columnDefs` are not mutated, but `api.getColumnDefs()` includes dynamic calculated columns for persistence.
Calculated columns are managed through column definitions, like other columns. To add, update or remove a calculated column from application code, update the `columnDefs` grid option.

A column added from the header menu is placed after the column it was created from, where that anchor is a leaf column. When the anchor is a column-group header or the auto-group column, or when the anchor column is later removed, the calculated column falls back to the end of the column tree.

Replacing the grid's columns with `setColumnDefs` (or `updateGridOptions({ columnDefs })`) is a full reset: it clears calculated columns added through the API or the dialog. To keep user-created calculated columns across a replacement, read the current definitions from `api.getColumnDefs()` and include them in the new array.
A column added from the header menu is placed after the column it was created from. The dialog manages calculated columns inside the grid without mutating the `columnDefs` array supplied by the application. To persist user-created calculated columns, read the complete current definitions from `api.getColumnDefs()`.

```{% frameworkTransform=true %}
const calculatedColumns = api
.getColumns()
.filter(column => column.getColDef().calculatedExpression != null);

api.addCalculatedColumn({
colId: 'profitMargin',
calculatedExpression: '([revenue] - [cost]) / [revenue]',
cellDataType: 'number',
valueFormatter: params => `${(params.value * 100).toFixed(1)}%`,
});
api.setGridOption('columnDefs', [
...(api.getColumnDefs() ?? []),
{
colId: 'profitMargin',
calculatedExpression: '([revenue] - [cost]) / [revenue]',
cellDataType: 'number',
valueFormatter: params => `${(params.value * 100).toFixed(1)}%`,
},
]);

api.updateCalculatedColumn('profitMargin', {
calculatedExpression: '([revenue] - [cost]) / [revenue]',
valueFormatter: params => `${(params.value * 100).toFixed(2)}%`,
});
api.setGridOption(
'columnDefs',
(api.getColumnDefs() ?? []).map(colDef =>
colDef.colId === 'profitMargin'
? { ...colDef, calculatedExpression: '([revenue] - [cost]) / [revenue]' }
: colDef
)
);

api.openCalculatedColumnDialog('profitMargin');

api.removeCalculatedColumn('profitMargin');
api.setGridOption(
'columnDefs',
(api.getColumnDefs() ?? []).filter(colDef => colDef.colId !== 'profitMargin')
);
```

Calculated Column events also use stored `colId` references in their expression payloads. For example, an event raised from the dialog still reports `[revenue]`, not `[Revenue]`.
Expand All @@ -199,7 +207,7 @@ Calculated Column events also use stored `colId` references in their expression

### Grid API

{% apiDocumentation source="grid-api/api.json" section="calculatedColumns" names=["addCalculatedColumn", "updateCalculatedColumn", "removeCalculatedColumn", "openCalculatedColumnDialog"] /%}
{% apiDocumentation source="grid-api/api.json" section="calculatedColumns" names=["openCalculatedColumnDialog"] /%}

### Grid Options

Expand Down
26 changes: 0 additions & 26 deletions packages/ag-grid-community/src/api/gridApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import type {
} from '../interfaces/autoSize';
import type { CsvExportParams } from '../interfaces/exportParams';
import type { GridState, GridStateKey } from '../interfaces/gridState';
import type { CalculatedColumnDef, CalculatedColumnUpdate } from '../interfaces/iCalculatedColumns';
import type { RenderedRowEvent } from '../interfaces/iCallbackParams';
import type {
EditingCellPosition,
Expand Down Expand Up @@ -1780,31 +1779,6 @@ export interface _FormulaGridApi<TData = any> {

/** @internal AG_GRID_INTERNAL - Not for public use. Can change / be removed at any time. */
export interface _CalculatedColumnsGridApi<TData = any> {
/**
* Add a new calculated column to the end of the column definitions.
* The `calculatedExpression` should reference other columns by `colId`, e.g. `[revenue] - [cost]`.
* @agModule `CalculatedColumnsModule`
*/
addCalculatedColumn<TValue = any>(colDef: CalculatedColumnDef<TData, TValue>): void;

/**
* Update an existing calculated column.
* The `calculatedExpression` should reference other columns by `colId`, e.g. `[revenue] - [cost]`.
* No-op if the supplied column key does not resolve to a calculated column.
* @agModule `CalculatedColumnsModule`
*/
updateCalculatedColumn<TValue = any>(
column: ColKey<TData, TValue>,
colDef: CalculatedColumnUpdate<TData, TValue>
): void;

/**
* Remove an existing calculated column.
* No-op if the supplied column key does not resolve to a calculated column.
* @agModule `CalculatedColumnsModule`
*/
removeCalculatedColumn(column: ColKey<TData>): void;

/**
* Open the Calculated Column dialog for an existing calculated column.
* No-op if the supplied column key does not resolve to a calculated column.
Expand Down
3 changes: 0 additions & 3 deletions packages/ag-grid-community/src/api/gridApiFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -379,9 +379,6 @@ export const gridApiFunctionsMap: Record<keyof GridApi, ValidationModuleName> =
}),

...mod<_CalculatedColumnsGridApi<any>>('CalculatedColumns', {
addCalculatedColumn: 0,
updateCalculatedColumn: 0,
removeCalculatedColumn: 0,
openCalculatedColumnDialog: 0,
}),

Expand Down
4 changes: 2 additions & 2 deletions packages/ag-grid-community/src/columns/columnStateUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export function _applyColumnState(
colIds[i] = state[i].colId;
}
if (calculatedColsSvc?.restoreDynamicColumnDefs(colIds)) {
colModel.refreshDynamicColumns(source);
calculatedColsSvc.refreshProjectedColumns(source);
}
}

Expand Down Expand Up @@ -301,7 +301,7 @@ export function _resetColumnState(beans: BeanCollection, source: ColumnEventType
const { colModel, autoColSvc, selectionColSvc, eventSvc, gos, calculatedColsSvc } = beans;

if (calculatedColsSvc?.resetDynamicColumnDefs(true)) {
colModel.refreshDynamicColumns(source);
calculatedColsSvc.refreshProjectedColumns(source);
}

const primaryCols = colModel.getColDefCols();
Expand Down
14 changes: 7 additions & 7 deletions packages/ag-grid-community/src/interfaces/iCalculatedColumns.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Bean } from '../context/bean';
import type { AgColumn } from '../entities/agColumn';
import type { ColDef, ColGroupDef, ColKey } from '../entities/colDef';
import type { ColDef, ColGroupDef } from '../entities/colDef';
import type { ColumnEventType } from '../events';

export type CalculatedColumnExpressionPicker = 'columns' | 'functions' | 'operators';

Expand All @@ -17,10 +18,10 @@ export interface CalculatedColumnsOptions {
*/
expressionPickers?: CalculatedColumnExpressionPicker[] | null;
/**
* Highlight the calculated column currently being edited by the dialog.
* Suppress highlighting the calculated column currently being edited by the dialog.
* @default false
*/
columnHighlighting?: boolean;
suppressColumnHighlighting?: boolean;
}

export type CalculatedColumnDef<TData = any, TValue = any> = ColDef<TData, TValue> & {
Expand All @@ -33,14 +34,13 @@ export type CalculatedColumnUpdate<TData = any, TValue = any> = Partial<ColDef<T
};

export interface ICalculatedColumnsService extends Bean {
addCalculatedColumn(colDef: CalculatedColumnDef, source?: 'api' | 'calculatedColumn'): void;
updateCalculatedColumn(column: ColKey, colDef: CalculatedColumnUpdate, source?: 'api' | 'calculatedColumn'): void;
removeCalculatedColumn(column: AgColumn | null, source?: 'api' | 'calculatedColumn'): void;
openCalculatedColumnDialog(column: AgColumn | null, mode: 'add' | 'edit'): void;
removeCalculatedColumn(column: AgColumn | null): void;
openCalculatedColumnDialog(column: AgColumn | null, mode: 'add' | 'edit', focusDialog?: boolean): void;
createProjectedColumnDefs(columnDefs: (ColDef | ColGroupDef)[] | undefined): (ColDef | ColGroupDef)[] | undefined;
orderDynamicColumns(columns: AgColumn[]): void;
shouldPreserveColumnOrderOnRefresh(): boolean;
resetDynamicColumnDefs(preserveCreatedColumns?: boolean): boolean;
restoreDynamicColumnDefs(colIds: string[]): boolean;
refreshProjectedColumns(source: ColumnEventType): void;
isHighlightedColumn(column: AgColumn | null): boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ const GRID_OPTION_VALIDATIONS: () => Validations<GridOptions> = () => {
return 'calculatedColumns should be an object.';
}

const { dataTypes, expressionPickers, columnHighlighting } = calculatedColumns;
const { dataTypes, expressionPickers, suppressColumnHighlighting } = calculatedColumns;
if (dataTypes != null) {
if (!Array.isArray(dataTypes) || dataTypes.some((dataType) => typeof dataType !== 'string')) {
return 'calculatedColumns.dataTypes should be an array of strings.';
Expand All @@ -201,8 +201,8 @@ const GRID_OPTION_VALIDATIONS: () => Validations<GridOptions> = () => {
return "calculatedColumns.expressionPickers should contain only 'columns', 'functions' or 'operators'.";
}
}
if (columnHighlighting != null && typeof columnHighlighting !== 'boolean') {
return 'calculatedColumns.columnHighlighting should be a boolean.';
if (suppressColumnHighlighting != null && typeof suppressColumnHighlighting !== 'boolean') {
return 'calculatedColumns.suppressColumnHighlighting should be a boolean.';
}

return null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,5 @@
import type { BeanCollection, CalculatedColumnDef, CalculatedColumnUpdate, ColKey } from 'ag-grid-community';

export function addCalculatedColumn(beans: BeanCollection, colDef: CalculatedColumnDef): void {
beans.calculatedColsSvc?.addCalculatedColumn(colDef);
}

export function updateCalculatedColumn(beans: BeanCollection, column: ColKey, colDef: CalculatedColumnUpdate): void {
beans.calculatedColsSvc?.updateCalculatedColumn(column, colDef);
}

export function removeCalculatedColumn(beans: BeanCollection, column: ColKey): void {
beans.calculatedColsSvc?.removeCalculatedColumn(beans.colModel.getColDefColOrCol(column));
}
import type { BeanCollection, ColKey } from 'ag-grid-community';

export function openCalculatedColumnDialog(beans: BeanCollection, column: ColKey): void {
beans.calculatedColsSvc?.openCalculatedColumnDialog(beans.colModel.getColDefColOrCol(column), 'edit');
beans.calculatedColsSvc?.openCalculatedColumnDialog(beans.colModel.getColDefColOrCol(column), 'edit', false);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,7 @@ import { ColumnApiModule, TooltipModule, _PopupModule } from 'ag-grid-community'
import { FormulaModule } from '../formula/formulaModule';
import { VERSION } from '../version';
import calculatedColumnsCSS from './calculatedColumns.css';
import {
addCalculatedColumn,
openCalculatedColumnDialog,
removeCalculatedColumn,
updateCalculatedColumn,
} from './calculatedColumnsApi';
import { openCalculatedColumnDialog } from './calculatedColumnsApi';
import { CalculatedColumnsService } from './calculatedColumnsService';

/**
Expand All @@ -20,9 +15,6 @@ export const CalculatedColumnsModule: _ModuleWithApi<_CalculatedColumnsGridApi<a
version: VERSION,
beans: [CalculatedColumnsService],
apiFunctions: {
addCalculatedColumn,
updateCalculatedColumn,
removeCalculatedColumn,
openCalculatedColumnDialog,
},
dependsOn: [FormulaModule, _PopupModule, ColumnApiModule, TooltipModule],
Expand Down
Loading
Loading