From 30edad956992a7e65b3887c0214056d655382fdc Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Thu, 30 Apr 2026 13:03:03 +0300 Subject: [PATCH 1/3] fix(pivot-grid): fix date format based on the localization --- .../grids/core/src/pivot-grid-dimensions.ts | 28 ++++++++++++++++++- .../grids/core/src/pivot-grid.interface.ts | 13 +++++++++ .../grids/pivot-grid/src/pivot-grid.spec.ts | 3 +- .../pivot-row-dimension-content.component.ts | 6 +++- 4 files changed, 47 insertions(+), 3 deletions(-) diff --git a/projects/igniteui-angular/grids/core/src/pivot-grid-dimensions.ts b/projects/igniteui-angular/grids/core/src/pivot-grid-dimensions.ts index 96efe72ff2a..70b50f6457b 100644 --- a/projects/igniteui-angular/grids/core/src/pivot-grid-dimensions.ts +++ b/projects/igniteui-angular/grids/core/src/pivot-grid-dimensions.ts @@ -139,7 +139,33 @@ 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; + // When fullDate is enabled and the user has not provided a custom memberFunction, + // attach a locale-aware formatter so the leaf date values are displayed in + // short-date format instead of the raw data string. + // When the user provides their own memberFunction, the dimension is used as-is + // (spread-create is skipped) to avoid overriding the user's intended formatting. + let baseDimension: IPivotDimension = null; + if (options.fullDate) { + if (inBaseDimension.memberFunction) { + // User supplied a custom memberFunction — preserve it without adding a formatter. + baseDimension = inBaseDimension; + } else { + // No custom memberFunction: create a new dimension object with a locale-aware + // formatter that shows dates in short-date format. + baseDimension = { + ...inBaseDimension, + formatter: (value: any) => { + const dateValue = (value !== null && value !== undefined && value !== '') + ? getDateFormatter().createDateFromValue(value) + : null; + return dateValue + ? getDateFormatter().formatDateTime(dateValue, undefined, { dateStyle: 'short' }) + : value; + } + }; + } + } + const monthDimensionDef: IPivotDimension = { memberName: 'Months', memberFunction: (rec) => { diff --git a/projects/igniteui-angular/grids/core/src/pivot-grid.interface.ts b/projects/igniteui-angular/grids/core/src/pivot-grid.interface.ts index edbb95dc676..c57661c2321 100644 --- a/projects/igniteui-angular/grids/core/src/pivot-grid.interface.ts +++ b/projects/igniteui-angular/grids/core/src/pivot-grid.interface.ts @@ -140,6 +140,19 @@ export interface IPivotDimension { /** @hidden @internal */ autoWidth?: number; horizontalSummary? : boolean; + /** + * Optional function to format the display value of a dimension cell. + * Unlike `memberFunction`, this does not affect the data key used for grouping or sorting — + * it is applied only when rendering the dimension header text. + * When set, the return value of this function is shown instead of the raw dimension value. + * + * @example + * ```typescript + * // Display dates in a locale-aware short date format. + * { memberName: 'Date', enabled: true, formatter: (value) => new Date(value).toLocaleDateString() } + * ``` + */ + formatter?: (value: any) => string; } /* marshalByValue */ diff --git a/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.spec.ts b/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.spec.ts index aa353b4ed15..11bf742a49a 100644 --- a/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.spec.ts +++ b/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.spec.ts @@ -1245,7 +1245,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(undefined, { 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); diff --git a/projects/igniteui-angular/grids/pivot-grid/src/pivot-row-dimension-content.component.ts b/projects/igniteui-angular/grids/pivot-grid/src/pivot-row-dimension-content.component.ts index 5abfa05e44b..fa0874127d2 100644 --- a/projects/igniteui-angular/grids/pivot-grid/src/pivot-row-dimension-content.component.ts +++ b/projects/igniteui-angular/grids/pivot-grid/src/pivot-row-dimension-content.component.ts @@ -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.formatter != null) { + header = dim.formatter(rawHeader) ?? rawHeader; + } const col = this._createColComponent(field, header, dim); return col; } From 6c68a01dab66c25174c66bfe613c98b4d342cc7b Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Thu, 30 Apr 2026 15:15:34 +0300 Subject: [PATCH 2/3] fix(pivot-grid): update with fixes --- .../grids/core/src/pivot-grid-dimensions.ts | 12 ++++++------ .../grids/core/src/pivot-grid.interface.ts | 7 +++++-- .../grids/pivot-grid/src/pivot-grid.component.ts | 4 +++- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/projects/igniteui-angular/grids/core/src/pivot-grid-dimensions.ts b/projects/igniteui-angular/grids/core/src/pivot-grid-dimensions.ts index 70b50f6457b..eaceaca8a46 100644 --- a/projects/igniteui-angular/grids/core/src/pivot-grid-dimensions.ts +++ b/projects/igniteui-angular/grids/core/src/pivot-grid-dimensions.ts @@ -170,8 +170,8 @@ export class IgxPivotDateDimension implements IPivotDimension { memberName: 'Months', memberFunction: (rec) => { const recordValue = PivotUtil.extractValueFromDimension(inBaseDimension, rec); - const dateValue = recordValue ? getDateFormatter().createDateFromValue(recordValue) : null; - return recordValue ? getDateFormatter().formatDateTime(dateValue, undefined, { month: 'long'}) : rec['Months']; + const dateValue = (recordValue != null && recordValue !== '') ? getDateFormatter().createDateFromValue(recordValue) : null; + return (recordValue != null && recordValue !== '') ? getDateFormatter().formatDateTime(dateValue, undefined, { month: 'long'}) : rec['Months']; }, enabled: true, childLevel: baseDimension @@ -182,8 +182,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 (recordValue != null && recordValue !== '') ? `Q` + Math.ceil((dateValue.getMonth() + 1) / 3) : rec['Quarters']; }, enabled: true, childLevel: monthDimension @@ -194,8 +194,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 (recordValue != null && recordValue !== '') ? dateValue.getFullYear().toString() : rec['Years']; }, enabled: true, childLevel: quarterDimension diff --git a/projects/igniteui-angular/grids/core/src/pivot-grid.interface.ts b/projects/igniteui-angular/grids/core/src/pivot-grid.interface.ts index c57661c2321..318c4dc925c 100644 --- a/projects/igniteui-angular/grids/core/src/pivot-grid.interface.ts +++ b/projects/igniteui-angular/grids/core/src/pivot-grid.interface.ts @@ -143,8 +143,9 @@ export interface IPivotDimension { /** * Optional function to format the display value of a dimension cell. * Unlike `memberFunction`, this does not affect the data key used for grouping or sorting — - * it is applied only when rendering the dimension header text. + * 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 @@ -152,7 +153,9 @@ export interface IPivotDimension { * { memberName: 'Date', enabled: true, formatter: (value) => new Date(value).toLocaleDateString() } * ``` */ - formatter?: (value: any) => string; + /* csTreatAsEvent: PivotDimensionFormatterEventHandler */ + /* blazorOnlyScript */ + formatter?: (value: any) => string | null | undefined; } /* marshalByValue */ diff --git a/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.ts b/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.ts index 5a3d920d719..9cce3cf4132 100644 --- a/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.ts +++ b/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.ts @@ -2380,7 +2380,9 @@ 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 rawHeader = parent != null ? key.split(parent.field + this.pivotKeys.columnDimensionSeparator)[1] : key; + const dim = value.dimension as IPivotDimension; + ref.instance.header = dim?.formatter != null ? (dim.formatter(rawHeader) ?? rawHeader) : rawHeader; ref.instance.field = key; ref.instance.parent = parent; if (value.dimension.width) { From 1027bbdd876256823a187f4ad0853b0820b930f3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Apr 2026 13:47:02 +0000 Subject: [PATCH 3/3] fix(pivot-grid): only add default formatter when inBaseDimension.formatter is not set; remove memberFunction gate Agent-Logs-Url: https://github.com/IgniteUI/igniteui-angular/sessions/6a4f5653-eb5e-4555-82d8-ad0464847dcf Co-authored-by: Hristo313 <57346540+Hristo313@users.noreply.github.com> --- .../grids/core/src/pivot-grid-dimensions.ts | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/projects/igniteui-angular/grids/core/src/pivot-grid-dimensions.ts b/projects/igniteui-angular/grids/core/src/pivot-grid-dimensions.ts index eaceaca8a46..d0ecc66987e 100644 --- a/projects/igniteui-angular/grids/core/src/pivot-grid-dimensions.ts +++ b/projects/igniteui-angular/grids/core/src/pivot-grid-dimensions.ts @@ -139,28 +139,27 @@ export class IgxPivotDateDimension implements IPivotDimension { this.enabled = inBaseDimension.enabled; this.displayName = inBaseDimension.displayName || this.resourceStrings.igx_grid_pivot_date_dimension_total; - // When fullDate is enabled and the user has not provided a custom memberFunction, - // attach a locale-aware formatter so the leaf date values are displayed in - // short-date format instead of the raw data string. - // When the user provides their own memberFunction, the dimension is used as-is - // (spread-create is skipped) to avoid overriding the user's intended formatting. + // When fullDate is enabled, attach a locale-aware formatter unless the user has + // already supplied their own formatter on inBaseDimension. + // The memberFunction (if any) is kept intact via the spread — the formatter is + // a separate display-only concern and should not be gated on memberFunction. let baseDimension: IPivotDimension = null; if (options.fullDate) { - if (inBaseDimension.memberFunction) { - // User supplied a custom memberFunction — preserve it without adding a formatter. + if (inBaseDimension.formatter) { + // User supplied their own formatter — use the dimension as-is. baseDimension = inBaseDimension; } else { - // No custom memberFunction: create a new dimension object with a locale-aware + // No user-supplied formatter: create a new dimension object with a locale-aware // formatter that shows dates in short-date format. baseDimension = { ...inBaseDimension, formatter: (value: any) => { - const dateValue = (value !== null && value !== undefined && value !== '') - ? getDateFormatter().createDateFromValue(value) - : null; - return dateValue - ? getDateFormatter().formatDateTime(dateValue, undefined, { dateStyle: 'short' }) - : value; + const hasValue = value !== null && value !== undefined && value !== ''; + const dateValue = hasValue ? getDateFormatter().createDateFromValue(value) : null; + if (dateValue) { + return getDateFormatter().formatDateTime(dateValue, undefined, { dateStyle: 'short' }); + } + return hasValue ? String(value) : ''; } }; }