UNPKG

ag-grid-community

Version:

Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue

395 lines (394 loc) 17 kB
import type { GridApi } from '../api/gridApi'; import type { ColDef } from '../entities/colDef'; import type { Column } from '../interfaces/iColumn'; import type { IRowNode } from '../interfaces/iRowNode'; import type { BaseColDefOptionalDataParams, ColumnFunctionCallbackParams } from './colDef-base'; /** * Parameters passed to the `groupRowEditable` callback. * * @example * ```ts * colDef.groupRowEditable = (params) => { * // Only allow editing on leaf-level groups * return params.node.childrenAfterGroup?.some(child => !child.group) ?? false; * }; * ``` */ export interface GroupRowEditableCallbackParams<TData = any, TValue = any, TContext = any> extends ColumnFunctionCallbackParams<TData, TValue, TContext> { } /** * Callback that determines whether a group row cell is editable. * * @returns `true` to allow editing, `false` to prevent it. */ export type GroupRowEditableCallback<TData = any, TValue = any, TContext = any> = (params: GroupRowEditableCallbackParams<TData, TValue, TContext>) => boolean; /** * Parameters passed to a `groupRowValueSetter` callback when a group row cell is edited. * * @example * ```ts * colDef.groupRowValueSetter = (params) => { * for (const child of params.aggregatedChildren) { * child.setDataValue(params.column, params.newValue, 'data'); * } * }; * ``` */ export interface GroupRowValueSetterParams<TData = any, TValue = any, TContext = any> { /** The grid api. */ api: GridApi<TData>; /** Application context as set on `gridOptions.context`. */ context: TContext; /** Column for this callback. */ column: Column<TValue>; /** ColDef provided for this column. */ colDef: ColDef<TData, TValue>; /** The value before the change. */ oldValue: TValue | null | undefined; /** The value after the change. */ newValue: TValue | null | undefined; /** The group row node being edited. */ node: IRowNode<TData>; /** Row data for the group node. `null` or `undefined` for grouping groups or tree data filler nodes. */ data: TData | null | undefined; /** What triggered the edit (e.g. `'ui'`, `'undo'`, `'paste'`). */ eventSource: string | undefined; /** Whether the aggregated value actually changed compared to the previous value. */ valueChanged: boolean; /** * The immediate children that contribute to this group's aggregation. * * - **Leaf groups** (groups directly containing data rows): the data rows themselves. * - **Non-leaf groups** (groups containing sub-groups): the child group rows. * Calling `setDataValue()` on a child group cascades the edit recursively through * the full hierarchy. The built-in `distributeGroupValue` does this automatically. * - **Pivot mode**: only rows matching the edited pivot column's keys are included. * * Use {@link IRowNode.getAggregatedChildren | rowNode.getAggregatedChildren(colKey)} * to retrieve the same children programmatically. Pass `true` as the second argument * to collect all descendant leaf rows recursively. * * Only supported with the Client-Side Row Model. */ aggregatedChildren: IRowNode<TData>[]; } /** * Custom callback for distributing a group row value edit to descendant rows. * * @returns `true` if at least one child value was changed, `false` otherwise. * Returning `void` or `undefined` is treated as `true`. * * @example * ```ts * // Custom: set all children to the edited value * colDef.groupRowValueSetter = (params) => { * let changed = false; * for (const child of params.aggregatedChildren) { * if (child.setDataValue(params.column, params.newValue, 'data')) { * changed = true; * } * } * return changed; * }; * ``` * * @example * ```ts * // Use the built-in distributeGroupValue with custom options * import { distributeGroupValue } from 'ag-grid-enterprise'; * * colDef.groupRowValueSetter = (params) => * distributeGroupValue(params, { distribution: 'percentage' }); * ``` */ export type GroupRowValueSetterFunc<TData = any, TValue = any, TContext = any> = (params: GroupRowValueSetterParams<TData, TValue, TContext>) => void | boolean | undefined; /** * Parameters passed to the {@link GroupRowValueSetterDistributionOptions.getValue | getValue} callback. * Extends the same base as `ValueGetterParams` — `node` is the child row being read, * `data` is `node.data`. Access the group edit context via `groupParams`. * * @example * ```ts * getValue: (params) => params.data?.weight ?? 0, * ``` */ export interface DistributionGetValueParams<TData = any, TValue = any, TContext = any> extends BaseColDefOptionalDataParams<TData, TValue, TContext> { /** The child RowNode whose value is being read. */ node: IRowNode<TData>; /** The group row edit parameters that triggered this distribution. */ groupParams: GroupRowValueSetterParams<TData, TValue, TContext>; } /** * Parameters passed to the {@link GroupRowValueSetterDistributionOptions.setValue | setValue} callback. * Same as {@link DistributionGetValueParams} plus the `value` to write. * * @example * ```ts * setValue: (params) => * params.node.setDataValue(params.column, Math.max(0, Number(params.value)), 'data'), * ``` */ export interface DistributionSetValueParams<TData = any, TValue = any, TContext = any> extends DistributionGetValueParams<TData, TValue, TContext> { /** The distributed value to write to this child. */ value: unknown; } /** * Strategy for distributing a group-level value edit across descendant rows. * * - **`'uniform'`** — Divides the new value equally among all children. * For `sum`, each child receives `newValue / childCount`. * For `avg`, each child is set to `newValue` directly (so the average equals the edited value). * - **`'percentage'`** — Scales each child proportionally, preserving relative weights. * Falls back to `'uniform'` when the current total is zero. * - **`'increment'`** — Distributes only the difference (`newValue − oldValue`) among children. * For `sum`, each child receives `delta / childCount` added to its current value. * For `avg`, the full delta is added to every child. * - **`'overwrite'`** — Writes `newValue` directly to every child. * * Use `false` or `null` to suppress distribution entirely — no child values are modified * and the cell is treated as not editable (overriding `groupRowEditable`). * * @example * ```ts * // Assign a strategy directly on the column definition * colDef.groupRowValueSetter = { distribution: 'percentage' }; * ``` */ export type GroupRowValueSetterDistribution = 'uniform' | 'percentage' | 'increment' | 'overwrite'; /** * A value in the `distribution` record. Can be: * - A {@link GroupRowValueSetterDistribution} strategy string (e.g. `'percentage'`). * - `true` — uses the built-in default for the aggFunc. Enables custom aggFuncs with `'overwrite'`. * Note: `count`/`min`/`max`/`first`/`last` are only enabled via explicit per-aggFunc record entries. * Useful for overriding `false`/`null` from a parent in deep-merge scenarios. * - `false` or `null` — suppresses distribution for this aggFunc * and makes the cell not editable when that aggFunc is active. * - `undefined` — inherits from the parent options (falls through to the default for that aggFunc). * - A {@link GroupRowValueSetterDistributionOptions} object with strategy and per-aggFunc overrides. * - A custom {@link GroupRowValueSetterFunc} callback for full control. * * @example * ```ts * distribution: { * sum: 'percentage', // strategy string * avg: { distribution: 'increment', precision: 0 }, // options object * count: true, // enable with built-in default * min: false, // suppress * myCustomAgg: (params) => { ... }, // custom callback * } * ``` */ export type GroupRowValueSetterDistributionEntry<TData = any, TValue = any, TContext = any> = GroupRowValueSetterDistribution | GroupRowValueSetterDistributionOptions | GroupRowValueSetterFunc<TData, TValue, TContext> | boolean | null | undefined; /** * Maps aggregation function names (e.g. `'sum'`, `'avg'`, or a custom name) to distribution entries. * Each entry can be a strategy string, an options object, a custom callback function, * or `false`/`null` to suppress distribution for that aggFunc. * Unmatched aggFuncs fall through to {@link GroupRowValueSetterOptions.default | default}, * then to the built-in defaults. * * @example * ```ts * colDef.groupRowValueSetter = { * distribution: { * sum: 'percentage', * avg: { distribution: 'increment' }, * myCustomAgg: (params) => { ... }, * count: false, * }, * }; * ``` */ export type GroupRowValueSetterDistributionRecord<TData = any, TValue = any, TContext = any> = Record<string, GroupRowValueSetterDistributionEntry<TData, TValue, TContext>>; /** * Distribution options that can be specified at the top level of {@link GroupRowValueSetterOptions} * (applying to all aggFuncs) or per aggFunc inside a `distribution` record entry. * Per-aggFunc fields inherit from the top-level options when not specified. * * @example * ```ts * colDef.groupRowValueSetter = { * distribution: { * sum: { distribution: 'percentage', precision: 2 }, * }, * }; * ``` */ export interface GroupRowValueSetterDistributionOptions { /** * Distribution strategy to use. See {@link GroupRowValueSetterDistribution} for details. * Set to `true` to use the built-in default. Enables custom aggFuncs with `'overwrite'`. * Note: `count`/`min`/`max`/`first`/`last` are only enabled via explicit per-aggFunc record entries. * Useful for overriding `false`/`null` from a parent in deep-merge scenarios. * Set to `false` or `null` to suppress distribution and make the cell not editable. * When `undefined`, inherits from the parent options. * * When omitted at all levels, defaults to `'uniform'` for `sum`, `'overwrite'` for `avg` * and columns without an aggFunc, * and disabled for `count`/`min`/`max`/`first`/`last` and custom aggFuncs. */ distribution?: GroupRowValueSetterDistribution | boolean | null; /** * Number of decimal places to round values written to **child rows** during distribution. * Spreads any rounding remainder across children so their total matches exactly. * * - `0` — integers (e.g. `10 / 3` → `[4, 3, 3]`) * - `2` — two decimals (e.g. `10 / 3` → `[3.34, 3.33, 3.33]`) * - `false` — disable rounding (overrides auto-detect) * - `undefined` (default) — auto-detect from the column definition: * `cellEditorParams.precision` if set, `0` if `cellEditorParams.step` is a whole number, * no rounding otherwise. * * Note: the group row's displayed value is re-computed by the `aggFunc` after distribution. * For `sum`, the sum of rounded children always honours the same precision. For other * aggregation functions like `avg`, the re-aggregated value may not — for example, * the average of integers is not necessarily an integer. * * Ignored for `bigint` columns — bigint values are always distributed as integers. * * @example * ```ts * // Round child values to integers * colDef.groupRowValueSetter = { precision: 0 }; * * // Round child values to 2 decimal places (e.g. currency) * colDef.groupRowValueSetter = { precision: 2 }; * ``` */ precision?: number | false; /** * Reads a child's current value during distribution. * Default: `node.getDataValue(column, 'value')`. * Override to read from a custom data structure or computed field. * * @returns The child's current value. * * @example * ```ts * getValue: (params) => params.data?.weight ?? 0, * ``` */ getValue?: (params: DistributionGetValueParams) => unknown; /** * Writes a distributed value to a child. * Default: `node.setDataValue(column, value, 'data')`. * Override to write to a custom data structure or apply transformations. * * @returns `true` if the value was changed, `false` otherwise. * * @example * ```ts * setValue: (params) => * // Apply a minimum of 0 before writing * params.node.setDataValue(params.column, Math.max(0, Number(params.value)), 'data'), * ``` */ setValue?: (params: DistributionSetValueParams) => boolean; } /** * Options for the built-in group row value distribution. * Assign to `colDef.groupRowValueSetter` or use `true` for defaults. * * **Defaults by aggFunc:** * - No aggFunc: `'overwrite'` (writes the edited value to all children) * - `sum`: `'uniform'` (divides equally) * - `avg`: `'overwrite'` (writes the edited value to all children) * - `count` / `min` / `max` / `first` / `last`: disabled by default (cell is not editable unless * explicitly enabled via a per-aggFunc record entry with `true` or `'overwrite'`) * - Custom aggFuncs: disabled by default (set a `distribution` or use `default` to enable) * * @example * ```ts * colDef.groupRowValueSetter = { * distribution: { sum: 'percentage', avg: 'increment' }, * precision: 0, * }; * ``` * * @example Per-aggFunc with custom callback: * ```ts * colDef.groupRowValueSetter = { * distribution: { * sum: 'percentage', * myCustomAgg: (params) => { * for (const child of params.aggregatedChildren) { * child.setDataValue(params.column, params.newValue, 'data'); * } * }, * }, * precision: 0, * }; * ``` * * @example Fallback handler for unmatched aggregation functions: * ```ts * colDef.groupRowValueSetter = { * distribution: { sum: 'percentage' }, * default: (params) => { * for (const child of params.aggregatedChildren) { * child.setDataValue(params.column, params.newValue, 'data'); * } * }, * }; * ``` * * @agModule `RowGroupingEditModule` */ export interface GroupRowValueSetterOptions<TData = any, TValue = any, TContext = any> extends Omit<GroupRowValueSetterDistributionOptions, 'distribution'> { /** * Distribution strategy or per-aggregation-function strategy map. * * **As a string:** applies the chosen {@link GroupRowValueSetterDistribution} strategy * to all aggregation functions. * * **As `true`:** enables distribution using built-in defaults for distributable aggregation * functions and custom aggFuncs (which get `'overwrite'`). * Note: `count`/`min`/`max`/`first`/`last` are only enabled via explicit per-aggFunc record entries. * Useful for overriding `false`/`null` from `defaultColDef` in deep-merge scenarios. * * **As `false` or `null`:** suppresses distribution and makes the cell not editable * (overriding `groupRowEditable`). * * **As a record:** maps aggFunc names to individual strategies, options objects, * or custom callbacks. Unmatched aggFuncs fall through to {@link default}, * then to the built-in defaults. * * @example * ```ts * // Single strategy * distribution: 'percentage' * * // Enable all aggFuncs with built-in defaults * distribution: true * * // Per-aggFunc record (entries can be strings, objects, functions, true, or false/null) * distribution: { sum: 'percentage', avg: 'increment', count: true, myAgg: (params) => { ... }, min: false } * ``` */ distribution?: GroupRowValueSetterDistribution | boolean | null | GroupRowValueSetterDistributionRecord<TData, TValue, TContext>; /** * Fallback for aggFuncs that don't have a specific distribution strategy. * When `distribution` is a record, applies to aggFuncs not listed in the record. * When `distribution` is omitted, applies only to custom (non-built-in) aggFuncs. * Ignored when `distribution` is a string (all aggFuncs use the specified strategy). * * Accepts the same values as record entries: * - A function for full custom handling. * - A strategy string (e.g. `'overwrite'`). * - `false` or `null` to suppress distribution and make unmatched aggFunc cells not editable. * - An options object with strategy and precision. * * @example * ```ts * // Custom handler * default: (params) => { * for (const child of params.aggregatedChildren) { * child.setDataValue(params.column, params.newValue, 'data'); * } * } * * // Suppress all unmatched aggFuncs * default: false * ``` */ default?: GroupRowValueSetterDistributionEntry<TData, TValue, TContext>; }