Skip to content

Commit 5f910f9

Browse files
authored
Merge pull request #9999 from IgniteUI/rkaraivanov/formatter-data-row-context
feat(grid): Provide row data as argument to column formatter
2 parents 7eef284 + cd6955d commit 5f910f9

File tree

14 files changed

+74
-36
lines changed

14 files changed

+74
-36
lines changed

CHANGELOG.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
All notable changes for each version of this project will be documented in this file.
44

5+
## 12.1.2
6+
- `igxGrid`
7+
- The column formatter callback signature now accepts the row data as an additional argument:
8+
```typescript formatter(value: any, rowData?: any)```
9+
The `rowData` argument may be `undefined` in remote scenarios/applying the callback on filtering labels
10+
so make sure to check its availability.
11+
512
## 12.1.0
613

714
### New Features
@@ -32,7 +39,7 @@ All notable changes for each version of this project will be documented in this
3239
```
3340
- `IgxGrid`, `IgxTreeGrid`, `IgxHierarchicalGrid`
3441
- Added `batchEditing` - an `Input` property for controlling what type of transaction service is provided for the grid.
35-
Setting `<igx-grid [batchEditing]="true">` is the same as providing `[{ provide: IgxGridTransaction, useClass: IgxTransactionService }]`.
42+
Setting `<igx-grid [batchEditing]="true">` is the same as providing `[{ provide: IgxGridTransaction, useClass: IgxTransactionService }]`.
3643
- **Deprecation** - Providing a transaction service for the grid via `providers: [IgxTransactionService]` is now deprecated and will be removed in a future patch.
3744
Instead, use the new `batchEditing` property to control the grid's Transactions.
3845

@@ -46,14 +53,14 @@ All notable changes for each version of this project will be documented in this
4653
- `IgxGridCellComponent`, `IgxTreeGridCellComponent`, `IgxHierarchicalGridCellComponent` are no longer exposed in the public API. Instead, a new class `IgxGridCell` replaces all of these. It is a facade class which exposes only the public API of the above mentioned. Automatic migration will change these imports with `CellType`, which is the interface implemented by `IgxGridCell`
4754
- **Behavioral changes**
4855
- `getCellByKey`, `getCellByColumn`, `getCellByColumnVisibleIndex`, `row.cells`, `column.cells`, `grid.selectedCells` now return an `IgxGridCell` the `CellType` interface.
49-
- `cell` in `IGridCellEventArgs` is now `CellType`. `IGridCellEventArgs` are emitetd in `cellClick`, `selected`, `contextMenu` and `doubleClick` events.
56+
- `cell` in `IGridCellEventArgs` is now `CellType`. `IGridCellEventArgs` are emitetd in `cellClick`, `selected`, `contextMenu` and `doubleClick` events.
5057
- `let-cell` property in cell template is now `CellType`.
5158
- `getCellByColumnVisibleIndex` is now deprecated and will be removed in next major version. Use `getCellByKey`, `getCellByColumn` instead.
5259

5360
- `Transactions`
5461
- Added `IgxFlatTransactionFactory` - the singleton service instantiates a new `TransactionService<Transaction, State>` given a `transaction type`.
5562
- Added `IgxHierarchicalTransactionFactory` - the singleton service instantiates a new `HierarchicalTransactionService<HierarchicalTransaction, HierarchicalState>` given a `transaction type`.
56-
63+
5764
- `Toolbar Actions`
5865
- Exposed a new input property `overlaySettings` for all column actions (`hiding` | `pinning` | `advanced filtering` | `exporter`). Example below:
5966

projects/igniteui-angular/src/lib/grids/cell.component.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
[groupName]="gridID"
1818
[value]="
1919
formatter
20-
? (value | columnFormatter: formatter)
20+
? (value | columnFormatter:formatter:rowData)
2121
: column.dataType === 'number'
2222
? (value | number:column.pipeArgs.digitsInfo:grid.locale)
2323
: (column.dataType === 'date' || column.dataType === 'time' || column.dataType === 'dateTime')
@@ -34,7 +34,7 @@
3434
[metadata]="searchMetadata"
3535
>{{
3636
formatter
37-
? (value | columnFormatter: formatter)
37+
? (value | columnFormatter:formatter:rowData)
3838
: column.dataType === "number"
3939
? (value | number:column.pipeArgs.digitsInfo:grid.locale)
4040
: (column.dataType === 'date' || column.dataType === 'time' || column.dataType === 'dateTime')
@@ -56,7 +56,7 @@
5656
[cssClass]="highlightClass"
5757
[activeCssClass]="activeHighlightClass"
5858
[groupName]="gridID"
59-
[value]="formatter ? (value | columnFormatter:formatter) : column.dataType === 'number' ?
59+
[value]="formatter ? (value | columnFormatter:formatter:rowData) : column.dataType === 'number' ?
6060
(value | number:column.pipeArgs.digitsInfo:grid.locale) : (column.dataType === 'date' || column.dataType === 'time' || column.dataType === 'dateTime') ?
6161
(value | date:column.pipeArgs.format:column.pipeArgs.timezone:grid.locale) : column.dataType === 'currency' ?
6262
(value | currency:currencyCode:column.pipeArgs.display:column.pipeArgs.digitsInfo:grid.locale) : column.dataType === 'percent' ?

projects/igniteui-angular/src/lib/grids/cell.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
154154
* @memberof IgxGridCellComponent
155155
*/
156156
@Input()
157-
public formatter: (value: any) => any;
157+
public formatter: (value: any, rowData?: any) => any;
158158

159159
/**
160160
* Gets the cell template context object.
@@ -304,7 +304,7 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
304304

305305
@HostBinding('attr.title')
306306
public get title() {
307-
return this.editMode || this.cellTemplate ? '' : this.formatter ? this.formatter(this.value) :
307+
return this.editMode || this.cellTemplate ? '' : this.formatter ? this.formatter(this.value, this.rowData) :
308308
this.column.dataType === GridColumnDataType.Percent ?
309309
this.grid.percentPipe.transform(this.value, this.column.pipeArgs.digitsInfo, this.grid.locale) :
310310
this.column.dataType === GridColumnDataType.Currency ?

projects/igniteui-angular/src/lib/grids/columns/column.component.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -576,12 +576,17 @@ export class IgxColumnComponent implements AfterContentInit, OnDestroy {
576576
@Input()
577577
public cellStyles = null;
578578
/**
579-
* When autogenerating columns, the formatter is used to format the display of the column data
580-
* without modifying the underlying bound values.
579+
* Applies display format to cell values in the column. Does not modify the underlying data.
580+
*
581+
* @remark
582+
* Note: As the formatter is used in places like the Excel style filtering dialog, in certain
583+
* scenarios (remote filtering for example), the row data argument can be `undefined`.
584+
*
581585
*
582586
* In this example, we check to see if the column name is Salary, and then provide a method as the column formatter
583587
* to format the value into a currency string.
584588
*
589+
* @example
585590
* ```typescript
586591
* columnInit(column: IgxColumnComponent) {
587592
* if (column.field == "Salary") {
@@ -594,12 +599,19 @@ export class IgxColumnComponent implements AfterContentInit, OnDestroy {
594599
* }
595600
* ```
596601
*
602+
* @example
603+
* ```typescript
604+
* const column = this.grid.getColumnByName('Address');
605+
* const addressFormatter = (address: string, rowData: any) => data.privacyEnabled ? 'unknown' : address;
606+
* column.formatter = addressFormatter;
607+
* ```
608+
*
597609
* @memberof IgxColumnComponent
598610
*/
599611
@notifyChanges()
600612
@WatchColumnChanges()
601613
@Input()
602-
public formatter: (value: any) => any;
614+
public formatter: (value: any, rowData?: any) => any;
603615

604616
/**
605617
* The summaryFormatter is used to format the display of the column summaries.

projects/igniteui-angular/src/lib/grids/common/pipes.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,8 @@ export class IgxGridTransactionStatePipe implements PipeTransform {
305305
@Pipe({ name: 'columnFormatter' })
306306
export class IgxColumnFormatterPipe implements PipeTransform {
307307

308-
public transform(value: any, formatter: (v: any) => any) {
309-
return formatter(value);
308+
public transform(value: any, formatter: (v: any, data: any) => any, rowData: any) {
309+
return formatter(value, rowData);
310310
}
311311
}
312312

projects/igniteui-angular/src/lib/grids/filtering/advanced-filtering/advanced-filtering-dialog.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ <h6 class="igx-filter-empty__title">
111111
{{
112112
isDate(expressionItem.expression.searchVal)
113113
? getFormatter(expressionItem.expression.fieldName)
114-
? (expressionItem.expression.searchVal | columnFormatter:getFormatter(expressionItem.expression.fieldName))
114+
? (expressionItem.expression.searchVal | columnFormatter:getFormatter(expressionItem.expression.fieldName):undefined)
115115
: (expressionItem.expression.searchVal | date:getFormat(expressionItem.expression.fieldName):undefined:grid.locale)
116116
: expressionItem.expression.searchVal
117117
}}

projects/igniteui-angular/src/lib/grids/filtering/excel-style/grid.excel-style-filtering.component.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -551,11 +551,11 @@ export class IgxGridExcelStyleFilteringComponent implements OnDestroy {
551551
const columnValues = (this.column.dataType === GridColumnDataType.Date) ?
552552
data.map(record => {
553553
const value = (resolveNestedPath(record, columnField));
554-
const label = this.getFilterItemLabel(value);
554+
const label = this.getFilterItemLabel(value, true, record);
555555
return { label, value };
556556
}) : data.map(record => {
557557
const value = resolveNestedPath(record, columnField);
558-
return shouldFormatValues ? this.column.formatter(value) : value;
558+
return shouldFormatValues ? this.column.formatter(value, record) : value;
559559
});
560560

561561
this.renderValues(columnValues);
@@ -784,33 +784,33 @@ export class IgxGridExcelStyleFilteringComponent implements OnDestroy {
784784
this.listData.unshift(blanks);
785785
}
786786

787-
private getFilterItemLabel(element: any, applyFormatter: boolean = true) {
787+
private getFilterItemLabel(element: any, applyFormatter: boolean = true, data?: any) {
788788
if (this.column.dataType === GridColumnDataType.Date || this.column.dataType === GridColumnDataType.Time ||
789789
this.column.dataType === GridColumnDataType.DateTime) {
790790
return element && element.label ? element.label : this.column.formatter ?
791-
applyFormatter ? this.column.formatter(element) : element :
791+
applyFormatter ? this.column.formatter(element, data) : element :
792792
this.grid.datePipe.transform(element, this.column.pipeArgs.format, this.column.pipeArgs.timezone,
793793
this.grid.locale);
794794
}
795795
if (this.column.dataType === GridColumnDataType.Number) {
796796
return this.column.formatter ?
797-
applyFormatter ? this.column.formatter(element) : element :
797+
applyFormatter ? this.column.formatter(element, data) : element :
798798
this.grid.decimalPipe.transform(element, this.column.pipeArgs.digitsInfo, this.grid.locale);
799799
}
800800
if (this.column.dataType === GridColumnDataType.Currency) {
801801
return this.column.formatter ?
802-
applyFormatter ? this.column.formatter(element) : element :
802+
applyFormatter ? this.column.formatter(element, data) : element :
803803
this.grid.currencyPipe.transform(element, this.column.pipeArgs.currencyCode ?
804804
this.column.pipeArgs.currencyCode : getLocaleCurrencyCode(this.grid.locale),
805805
this.column.pipeArgs.display, this.column.pipeArgs.digitsInfo, this.grid.locale);
806806
}
807807
if (this.column.dataType === GridColumnDataType.Percent) {
808808
return this.column.formatter ?
809-
applyFormatter ? this.column.formatter(element) : element :
809+
applyFormatter ? this.column.formatter(element, data) : element :
810810
this.grid.percentPipe.transform(element, this.column.pipeArgs.digitsInfo, this.grid.locale);
811811
}
812812
return this.column.formatter && applyFormatter ?
813-
this.column.formatter(element) :
813+
this.column.formatter(element, data) :
814814
element;
815815
}
816816

projects/igniteui-angular/src/lib/grids/filtering/grid-filtering.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ export class IgxFilteringService implements OnDestroy {
502502
const column = this.grid.getColumnByName(expression.fieldName);
503503
const formatter = column.formatter;
504504
if (formatter) {
505-
return formatter(expression.searchVal);
505+
return formatter(expression.searchVal, undefined);
506506
}
507507
const pipeArgs = column.pipeArgs;
508508
return this.grid.datePipe.transform(expression.searchVal, pipeArgs.format, undefined, this.grid.locale);

projects/igniteui-angular/src/lib/grids/grid-base.directive.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6762,9 +6762,9 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
67626762
columnsArray.forEach((col) => {
67636763
if (col) {
67646764
const key = headers ? col.header || col.field : col.field;
6765-
const value = source[row].ghostRecord ?
6766-
resolveNestedPath(source[row].recordRef, col.field) : resolveNestedPath(source[row], col.field);
6767-
record[key] = formatters && col.formatter ? col.formatter(value) : value;
6765+
const rowData = source[row].ghostRecord ? source[row].recordRef : source[row];
6766+
const value = resolveNestedPath(rowData, col.field);
6767+
record[key] = formatters && col.formatter ? col.formatter(value, rowData) : value;
67686768
if (columnData) {
67696769
if (!record[key]) {
67706770
record[key] = '';
@@ -6832,7 +6832,7 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
68326832
for (const data of source) {
68336833
selectedColumns.forEach((col) => {
68346834
const key = headers ? col.header || col.field : col.field;
6835-
record[key] = formatters && col.formatter ? col.formatter(data[col.field])
6835+
record[key] = formatters && col.formatter ? col.formatter(data[col.field], data)
68366836
: data[col.field];
68376837
});
68386838

@@ -7232,7 +7232,7 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
72327232
data.forEach((dataRow, rowIndex) => {
72337233
columnItems.forEach((c) => {
72347234
const pipeArgs = this.getColumnByName(c.field).pipeArgs;
7235-
const value = c.formatter ? c.formatter(resolveNestedPath(dataRow, c.field)) :
7235+
const value = c.formatter ? c.formatter(resolveNestedPath(dataRow, c.field), dataRow) :
72367236
c.dataType === 'number' ? this.decimalPipe.transform(resolveNestedPath(dataRow, c.field),
72377237
pipeArgs.digitsInfo, this.locale) :
72387238
c.dataType === 'date' ? this.datePipe.transform(resolveNestedPath(dataRow, c.field),

projects/igniteui-angular/src/lib/grids/grid/column.spec.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,21 @@ describe('IgxGrid - Column properties #grid', () => {
134134
}
135135
});
136136

137+
it('should correctly pass row data context for the format callback', () => {
138+
const fix = TestBed.createComponent(ColumnCellFormatterComponent);
139+
fix.detectChanges();
140+
141+
const grid = fix.componentInstance.grid;
142+
const formatter = fix.componentInstance.containsY;
143+
grid.getColumnByName('ID').formatter = formatter;
144+
fix.detectChanges();
145+
146+
for (let i = 0; i < 2; i++) {
147+
const cell = grid.gridAPI.get_cell_by_index(i, 'ID');
148+
expect(cell.nativeElement.textContent).toMatch('true');
149+
}
150+
});
151+
137152
it('should reflect the column in the DOM based on its index', () => {
138153
const fix = TestBed.createComponent(ColumnCellFormatterComponent);
139154
fix.detectChanges();

0 commit comments

Comments
 (0)