Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
2953430
Initial plan
Copilot Apr 29, 2026
7eb51a8
feat(pivot-grid): localize fullDate dimension display with shortDate …
Copilot Apr 29, 2026
118206a
chore: revert package-lock.json to original state
Copilot Apr 29, 2026
c5c8154
refactor(pivot-grid): improve readability of date formatter and test …
Copilot Apr 29, 2026
6e07821
fix(pivot-grid): address review comments on formatter type safety and…
Copilot Apr 30, 2026
859a146
refactor(pivot-grid): simplify formatter coercion to use nullish coal…
Copilot Apr 30, 2026
df731dc
Merge branch 'master' into copilot/fix-pivot-grid-date-localization
Hristo313 Apr 30, 2026
71b8391
Potential fix for pull request finding
Hristo313 Apr 30, 2026
1d40629
fix(pivot-grid): widen formatter return type to string | null | undef…
Copilot Apr 30, 2026
e92647b
fix(pivot-grid): address remaining review comments on formatter and d…
Copilot Apr 30, 2026
8a93e81
feat(pivot-grid): apply formatter to column dimension headers in crea…
Copilot Apr 30, 2026
b664a7a
fix(pivot-grid): revert copilot fix line
Hristo313 Apr 30, 2026
368595c
fix(pivot-grid): update with fixes
Hristo313 Apr 30, 2026
d97c5d3
Merge branch 'master' into copilot/fix-pivot-grid-date-localization
Hristo313 May 7, 2026
2c27c90
Merge branch 'master' into copilot/fix-pivot-grid-date-localization
Hristo313 May 13, 2026
2eddc5d
fix(pivot-grid): update with fixes
Hristo313 May 13, 2026
505fad5
Merge branch 'master' into copilot/fix-pivot-grid-date-localization
Hristo313 May 13, 2026
fdb6228
Merge branch 'master' into copilot/fix-pivot-grid-date-localization
Hristo313 May 19, 2026
37a8649
fix(pivot-grid): fix date dimension headers being one cycle behind on…
Copilot May 19, 2026
4d01b26
fix(pivot-grid): fix the locale change
Hristo313 May 19, 2026
43e129e
Changes before error encountered
Copilot Jun 29, 2026
21687d9
fix(pivot-grid): revert package-lock.json changes
Hristo313 Jun 29, 2026
b798cf0
Merge branch 'master' into copilot/fix-pivot-grid-date-localization
Hristo313 Jul 8, 2026
cd6bc7c
fix(pivot-grid): add small fixes
Hristo313 Jul 8, 2026
65b0df0
fix(pivot-grid): fix columns locale cycle behind
Hristo313 Jul 8, 2026
d2166c5
merge master
Hristo313 Jul 24, 2026
50b8cd7
fix(pivot-grid): revert pipes changes
Hristo313 Jul 24, 2026
cf5aa2e
fix(pivot-grid): fix failing test build
Hristo313 Jul 24, 2026
acd5a92
fix(pivot-grid): update with copilot suggestions
Hristo313 Jul 24, 2026
641c8ef
fix(pivot-grid): fix copilot suggestions
Hristo313 Jul 24, 2026
093c723
fix(pivot-grid): return old setupColumns logic
Hristo313 Jul 24, 2026
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ All notable changes for each version of this project will be documented in this
- Introduced the `selectionChanged` event for both components. The event is not cancelable and is emitted after the selection is committed and the component state is updated.
- Added `disableClear` input that allows hiding the clear button even when items are selected. Defaults to `false`.

- `IgxPivotGrid`
- Added `headerFormatter` optional property to `IPivotDimension`. This is a display-only callback `(value, dimension?, rowData?) => string | null | undefined` applied when rendering row and column dimension header text. Returning `null` or `undefined` falls back to the raw dimension value. The `IgxPivotDateDimension` uses this to render `fullDate` leaf values in a locale-aware short-date format automatically.

### General

- `IgxOverlayService`
Expand Down
45 changes: 36 additions & 9 deletions projects/igniteui-angular/grids/core/src/pivot-grid-dimensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,14 @@ export class IgxPivotDateDimension implements IPivotDimension {
public childLevel?: IPivotDimension;
/** @hidden @internal */
public memberName = 'AllPeriods';
/** @hidden @internal */
public locale?: string;
public displayName: string;
/**
* Gets/Sets the locale used for date dimension member formatting (e.g. month names).
* When set, overrides the global I18nManager locale for this dimension.
* Set automatically by the pivot grid component when the grid locale changes.
* @hidden @internal
*/
public locale?: string;
private _resourceStrings: IGridResourceStrings = null;
private _baseDimension: IPivotDimension;
private _options: IPivotDateDimensionOptions = {};
Expand Down Expand Up @@ -141,13 +146,16 @@ export class IgxPivotDateDimension implements IPivotDimension {
this.enabled = inBaseDimension.enabled;
this.displayName = inBaseDimension.displayName || this.resourceStrings.igx_grid_pivot_date_dimension_total;

const baseDimension = options.fullDate ? inBaseDimension : null;
const baseDimension: IPivotDimension = options.fullDate
? this.createLeafDateDimension(inBaseDimension)
: null;

const monthDimensionDef: IPivotDimension = {
memberName: 'Months',
memberFunction: (rec) => {
Comment on lines 153 to 155
const recordValue = PivotUtil.extractValueFromDimension(inBaseDimension, rec);
const dateValue = recordValue ? getDateFormatter().createDateFromValue(recordValue) : null;
return recordValue ? getDateFormatter().formatDateTime(dateValue, this.locale, { month: 'long'}) : rec['Months'];
const dateValue = (recordValue != null && recordValue !== '') ? getDateFormatter().createDateFromValue(recordValue) : null;
Comment thread
skrustev marked this conversation as resolved.
return dateValue ? getDateFormatter().formatDateTime(dateValue, this.locale, { month: 'long'}) : rec['Months'];
},
enabled: true,
childLevel: baseDimension
Expand All @@ -158,8 +166,8 @@ export class IgxPivotDateDimension implements IPivotDimension {
memberName: 'Quarters',
memberFunction: (rec) => {
const recordValue = PivotUtil.extractValueFromDimension(inBaseDimension, rec);
const dateValue = recordValue ? getDateFormatter().createDateFromValue(recordValue) : null;
return recordValue ? `Q` + Math.ceil((dateValue.getMonth() + 1) / 3) : rec['Quarters'];
const dateValue = (recordValue != null && recordValue !== '') ? getDateFormatter().createDateFromValue(recordValue) : null;
return dateValue ? `Q` + Math.ceil((dateValue.getMonth() + 1) / 3) : rec['Quarters'];
},
enabled: true,
childLevel: monthDimension
Expand All @@ -170,8 +178,8 @@ export class IgxPivotDateDimension implements IPivotDimension {
memberName: 'Years',
memberFunction: (rec) => {
const recordValue = PivotUtil.extractValueFromDimension(inBaseDimension, rec);
const dateValue = recordValue ? getDateFormatter().createDateFromValue(recordValue) : null;
return recordValue ? dateValue.getFullYear().toString() : rec['Years'];
const dateValue = (recordValue != null && recordValue !== '') ? getDateFormatter().createDateFromValue(recordValue) : null;
return dateValue ? dateValue.getFullYear().toString() : rec['Years'];
},
enabled: true,
childLevel: quarterDimension
Expand All @@ -187,6 +195,25 @@ export class IgxPivotDateDimension implements IPivotDimension {
}
}

private createLeafDateDimension(inBaseDimension: IPivotDimension): IPivotDimension {
if (inBaseDimension.headerFormatter || inBaseDimension.memberFunction) {
// User supplied their own formatter/memberFunction — use the dimension as-is.
return inBaseDimension;
}
Comment thread
Copilot marked this conversation as resolved.
// No user-supplied formatter: add a locale-aware formatter that shows dates
// in short-date format while preserving the original dimension instance.
const dateFormatter = getDateFormatter();
inBaseDimension.headerFormatter = (value: any) => {
const hasValue = value !== null && value !== undefined && value !== '';
const dateValue = hasValue ? dateFormatter.createDateFromValue(value) : null;
if (dateValue) {
return dateFormatter.formatDateTime(dateValue, this.locale, { dateStyle: 'short' });
}
return hasValue ? String(value) : '';
};
return inBaseDimension;
}

/** @hidden @internal */
public memberFunction = (_data) => this.resourceStrings.igx_grid_pivot_date_dimension_total;
}
16 changes: 16 additions & 0 deletions projects/igniteui-angular/grids/core/src/pivot-grid.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,22 @@ export interface IPivotDimension {
/** @hidden @internal */
autoWidth?: number;
horizontalSummary? : boolean;
/* csTreatAsEvent: PivotDimensionFormatterEventHandler */
/* blazorOnlyScript */
/**
* Optional function to format the display value of a dimension header.
* Unlike `memberFunction`, this does not affect the data key used for grouping or sorting —
* it is applied when rendering the dimension header text (both row and column dimension headers).
* When set, the return value of this function is shown instead of the raw dimension value.
* Return `null` or `undefined` to fall back to the raw value.
*
* @example
* ```typescript
* // Display dates in a locale-aware short date format.
* { memberName: 'Date', enabled: true, headerFormatter: (value) => new Date(value).toLocaleDateString() }
* ```
*/
Comment thread
Hristo313 marked this conversation as resolved.
headerFormatter?: (value: any, dimension?: IPivotDimension, rowData?: IPivotGridGroupRecord) => string | null | undefined;
}

/* marshalByValue */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2383,7 +2383,10 @@ export class IgxPivotGridComponent extends IgxGridBaseDirective implements OnIni
const ref = isGroup ?
createComponent(IgxColumnGroupComponent, { environmentInjector: this.envInjector, elementInjector: this.injector }) :
createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
ref.instance.header = parent != null ? key.split(parent.header + this.pivotKeys.columnDimensionSeparator)[1] : key;
const parentPath = parent != null ? parent.field + this.pivotKeys.columnDimensionSeparator : null;
const rawHeader = parentPath != null && key.startsWith(parentPath) ? key.substring(parentPath.length) : key;
const dim = value.dimension as IPivotDimension;
ref.instance.header = dim?.headerFormatter != null ? (dim.headerFormatter(rawHeader, dim, undefined) ?? rawHeader) : rawHeader;
ref.instance.field = key;
ref.instance.parent = parent;
if (value.dimension.width) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,30 @@ describe('IgxPivotGrid #pivotGrid', () => {
expect(actualDataTypeValue).toEqual('$71.89');
});

it('should provide context to dimension header formatter', () => {
const pivotGrid = fixture.componentInstance.pivotGrid;
const rowDimension = pivotGrid.pivotConfiguration.rows[0];
const headerFormatter = jasmine.createSpy('headerFormatter')
.and.callFake((value, dimension, rowData) => {
expect(dimension).toEqual(jasmine.objectContaining({ memberName: rowDimension.memberName }));
expect(rowData).toBeDefined();
return `formatted-${value}`;
});
rowDimension.headerFormatter = headerFormatter;

pivotGrid.pipeTrigger++;
pivotGrid.setupColumns();
fixture.detectChanges();

const rowHeaders = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent));
expect(rowHeaders[0].componentInstance.column.header).toBe('formatted-All');

const [rawValue, dimension, rowData] = headerFormatter.calls.mostRecent().args;
expect(rawValue).toBe('All');
expect(dimension).toEqual(jasmine.objectContaining({ memberName: rowDimension.memberName }));
expect(rowData.dimensionValues).toBeDefined();
});

it('should apply css class to cells from measures', () => {
fixture.detectChanges();
const pivotGrid = fixture.componentInstance.pivotGrid;
Expand Down Expand Up @@ -1245,7 +1269,8 @@ describe('IgxPivotGrid #pivotGrid', () => {
// check rows
const rows = pivotGrid.rowList.toArray();
expect(rows.length).toBe(5);
const expectedHeaders = ['All Periods', '2021', 'Q4', 'December', '12/08/2021'];
const formattedDate = Intl.DateTimeFormat(pivotGrid.locale, { dateStyle: 'short' }).format(new Date(2021, 11, 8));
const expectedHeaders = ['All Periods', '2021', 'Q4', 'December', formattedDate];
const rowHeaders = fixture.debugElement.queryAll(
By.directive(IgxPivotRowDimensionHeaderComponent));
const rowDimensionHeaders = rowHeaders.map(x => x.componentInstance.column.header);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,11 @@ export class IgxPivotRowDimensionContentComponent extends IgxGridHeaderRowCompon

protected extractFromDimension(dim: IPivotDimension, rowData: IPivotGridGroupRecord) {
const field = dim.memberName;
const header = rowData?.dimensionValues.get(field);
const rawHeader = rowData?.dimensionValues.get(field);
let header = rawHeader;
if (dim.headerFormatter != null) {
header = dim.headerFormatter(rawHeader, dim, rowData) ?? rawHeader;
}
Comment thread
Hristo313 marked this conversation as resolved.
Comment thread
Hristo313 marked this conversation as resolved.
const col = this._createColComponent(field, header, dim);
return col;
}
Expand Down
Loading