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..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,13 +139,38 @@ 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, 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.formatter) { + // User supplied their own formatter — use the dimension as-is. + baseDimension = inBaseDimension; + } else { + // 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 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) : ''; + } + }; + } + } + const monthDimensionDef: 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 @@ -156,8 +181,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 @@ -168,8 +193,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 edbb95dc676..318c4dc925c 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,22 @@ 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 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, formatter: (value) => new Date(value).toLocaleDateString() } + * ``` + */ + /* 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) { 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; }