Skip to content

Commit daa4509

Browse files
georgianastasovhanastasovddaribo
authored
feat(grid): add FormattedValuesSortingStrategy for sorting by formatted values - master (#14538)
* feat(grid): add FormattedValuesSortingStrategy for sorting by formatted values * docs(changelog): add info for new FormattedValuesSortingStrategy * docs(changelog): move the description for the feature from version 18.1 to 18.2 --------- Co-authored-by: Hristo <[email protected]> Co-authored-by: Bozhidara Pachilova <[email protected]>
1 parent ef0f767 commit daa4509

File tree

4 files changed

+153
-4
lines changed

4 files changed

+153
-4
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ All notable changes for each version of this project will be documented in this
66
### New Features
77
- `IgxSimpleCombo`
88
- Introduced ability for Simple Combo to automatically select and retain valid input on "Tab" press enhancing user experience by streamlining data entry and reducing the need for manual selection improving form navigation.
9+
- `IgxGrid`, `IgxTreeGrid`, `IgxHierarchicalGrid`
10+
- To streamline the sorting of columns with custom formats, a new `FormattedValuesSortingStrategy` has been introduced. This strategy simplifies the sorting process by allowing direct sorting based on formatted values, eliminating the need to extend the `DefaultSortingStrategy` or implement a custom `ISortingStrategy`. This enhancement improves the ease of handling sorting with custom column formatters.
911

1012
#### Scrollbar: New CSS variables
1113

projects/igniteui-angular/src/lib/data-operations/sorting-strategy.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,60 @@ export class GroupMemberCountSortingStrategy implements ISortingStrategy {
132132
return reverse * (firstItemValuesLength - secondItemValuesLength);
133133
}
134134
}
135+
136+
export class FormattedValuesSortingStrategy extends DefaultSortingStrategy {
137+
protected static override _instance: FormattedValuesSortingStrategy = null;
138+
139+
constructor() {
140+
super();
141+
}
142+
143+
public static override instance(): FormattedValuesSortingStrategy {
144+
return this._instance || (this._instance = new this());
145+
}
146+
147+
public override sort(
148+
data: any[],
149+
fieldName: string,
150+
dir: SortingDirection,
151+
ignoreCase: boolean,
152+
valueResolver: (obj: any, key: string, isDate?: boolean) => any,
153+
isDate?: boolean,
154+
isTime?: boolean,
155+
grid?: GridType
156+
) {
157+
const key = fieldName;
158+
const reverse = (dir === SortingDirection.Desc ? -1 : 1);
159+
const cmpFunc = (obj1: any, obj2: any) => this.compareObjects(obj1, obj2, key, reverse, ignoreCase, valueResolver, isDate, isTime, grid);
160+
return this.arraySort(data, cmpFunc);
161+
}
162+
163+
protected override compareObjects(
164+
obj1: any,
165+
obj2: any,
166+
key: string,
167+
reverse: number,
168+
ignoreCase: boolean,
169+
valueResolver: (obj: any, key: string, isDate?: boolean, isTime?: boolean) => any,
170+
isDate: boolean,
171+
isTime: boolean,
172+
grid?: GridType
173+
) {
174+
let a = valueResolver.call(this, obj1, key, isDate, isTime);
175+
let b = valueResolver.call(this, obj2, key, isDate, isTime);
176+
177+
if (grid) {
178+
const col = grid.getColumnByName(key);
179+
if (col && col.formatter) {
180+
a = col.formatter(a);
181+
b = col.formatter(b);
182+
}
183+
}
184+
185+
if (ignoreCase) {
186+
a = a && a.toLowerCase ? a.toLowerCase() : a;
187+
b = b && b.toLowerCase ? b.toLowerCase() : b;
188+
}
189+
return reverse * this.compareValues(a, b);
190+
}
191+
}

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

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import { TestBed, fakeAsync, tick } from '@angular/core/testing';
22
import { IgxGridComponent } from './grid.component';
3-
import { DefaultSortingStrategy, SortingDirection } from '../../data-operations/sorting-strategy';
3+
import { DefaultSortingStrategy, FormattedValuesSortingStrategy, SortingDirection } from '../../data-operations/sorting-strategy';
44
import { configureTestSuite } from '../../test-utils/configure-suite';
55
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
66
import { GridFunctions } from '../../test-utils/grid-functions.spec';
7-
import { GridDeclaredColumnsComponent, SortByParityComponent, GridWithPrimaryKeyComponent, SortByAnotherColumnComponent, SortOnInitComponent } from '../../test-utils/grid-samples.spec';
7+
import { GridDeclaredColumnsComponent, SortByParityComponent, GridWithPrimaryKeyComponent, SortByAnotherColumnComponent, SortOnInitComponent, IgxGridFormattedValuesSortingComponent } from '../../test-utils/grid-samples.spec';
88
import { UIInteractions } from '../../test-utils/ui-interactions.spec';
99
import { SampleTestData } from '../../test-utils/sample-test-data.spec';
1010
import { CellType } from '../common/grid.interface';
1111
import { NoopSortingStrategy } from '../common/strategy';
12+
import { By } from '@angular/platform-browser';
1213

1314
describe('IgxGrid - Grid Sorting #grid', () => {
1415

@@ -21,7 +22,8 @@ describe('IgxGrid - Grid Sorting #grid', () => {
2122
GridDeclaredColumnsComponent,
2223
SortByParityComponent,
2324
GridWithPrimaryKeyComponent,
24-
NoopAnimationsModule
25+
NoopAnimationsModule,
26+
IgxGridFormattedValuesSortingComponent
2527
]
2628
});
2729
}));
@@ -405,6 +407,58 @@ describe('IgxGrid - Grid Sorting #grid', () => {
405407
expect(grid.getCellByKey(6, 'LastName').row.index).toBeGreaterThan(grid.getCellByKey(7, 'LastName').row.index);
406408
expect(grid.getCellByKey(4, 'LastName').row.index).toBeGreaterThan(grid.getCellByKey(5, 'LastName').row.index);
407409
});
410+
411+
it('Should sort grid by formatted values using FormattedValuesSortingStrategy', fakeAsync(() => {
412+
fixture = TestBed.createComponent(IgxGridFormattedValuesSortingComponent);
413+
tick();
414+
fixture.detectChanges();
415+
416+
grid = fixture.componentInstance.grid;
417+
tick();
418+
fixture.detectChanges();
419+
420+
const productNameColumn = grid.getColumnByName("ProductName");
421+
const quantityColumn = grid.getColumnByName("QuantityPerUnit");
422+
423+
expect(productNameColumn.sortStrategy instanceof FormattedValuesSortingStrategy).toBeTruthy();
424+
expect(quantityColumn.sortStrategy instanceof FormattedValuesSortingStrategy).toBeTruthy();
425+
426+
const productNameHeaderCell = GridFunctions.getColumnHeader('ProductName', fixture);
427+
428+
GridFunctions.clickHeaderSortIcon(productNameHeaderCell);
429+
tick(30);
430+
fixture.detectChanges();
431+
432+
const firstProductNameCell = fixture.debugElement.queryAll(By.css('.igx-grid__td'))[1];
433+
expect(firstProductNameCell.nativeElement.textContent.trim()).toBe("a-Alice Mutton");
434+
435+
GridFunctions.clickHeaderSortIcon(productNameHeaderCell);
436+
tick(30);
437+
fixture.detectChanges();
438+
439+
const lastProductNameCell = fixture.debugElement.queryAll(By.css('.igx-grid__td'))[1];
440+
expect(lastProductNameCell.nativeElement.textContent.trim()).toBe("b-Tofu");
441+
442+
grid.clearSort();
443+
tick();
444+
fixture.detectChanges();
445+
446+
const quantityPerUnitHeaderCell = GridFunctions.getColumnHeader('QuantityPerUnit', fixture);
447+
448+
GridFunctions.clickHeaderSortIcon(quantityPerUnitHeaderCell);
449+
tick(30);
450+
fixture.detectChanges();
451+
452+
const firstQuantityCell = fixture.debugElement.queryAll(By.css('.igx-grid__td'))[2];
453+
expect(firstQuantityCell.nativeElement.textContent.trim()).toBe("c");
454+
455+
GridFunctions.clickHeaderSortIcon(quantityPerUnitHeaderCell);
456+
tick(30);
457+
fixture.detectChanges();
458+
459+
const lastQuantityCell = fixture.debugElement.queryAll(By.css('.igx-grid__td'))[2];
460+
expect(lastQuantityCell.nativeElement.textContent.trim()).toBe("d-36 boxes");
461+
}));
408462
});
409463

410464
describe('UI tests', () => {

projects/igniteui-angular/src/lib/test-utils/grid-samples.spec.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { ISortingOptions, IgxExcelStyleHeaderIconDirective, IgxGridToolbarAdvanc
1818
import { IgxRowAddTextDirective, IgxRowEditActionsDirective, IgxRowEditTabStopDirective, IgxRowEditTemplateDirective, IgxRowEditTextDirective } from '../grids/grid.rowEdit.directive';
1919
import { IgxExcelStyleColumnOperationsTemplateDirective, IgxExcelStyleFilterOperationsTemplateDirective, IgxGridExcelStyleFilteringComponent } from '../grids/filtering/excel-style/excel-style-filtering.component';
2020
import { FilteringLogic } from '../data-operations/filtering-expression.interface';
21-
import { ISortingStrategy, SortingDirection } from '../data-operations/sorting-strategy';
21+
import { FormattedValuesSortingStrategy, ISortingStrategy, SortingDirection } from '../data-operations/sorting-strategy';
2222
import { IgxActionStripComponent } from '../action-strip/action-strip.component';
2323
import { IDataCloneStrategy } from '../data-operations/data-clone-strategy';
2424
import { IgxColumnLayoutComponent } from '../grids/columns/column-layout.component';
@@ -2266,6 +2266,42 @@ export class SortOnInitComponent extends GridDeclaredColumnsComponent implements
22662266
}
22672267
}
22682268

2269+
@Component({
2270+
template: `
2271+
<igx-grid #grid [data]="data" [primaryKey]="'ProductID'" width="900px" height="600px">
2272+
<igx-column field="ProductID" header="Product ID" [sortable]="true"></igx-column>
2273+
<igx-column field="ProductName" header="Product Name" [dataType]="'string'" [sortable]="true"
2274+
[formatter]="formatProductName" [sortStrategy]="sortStrategy"></igx-column>
2275+
<igx-column field="QuantityPerUnit" header="Quantity Per Unit" [dataType]="'string'" [sortable]="true"
2276+
[formatter]="formatQuantity" [sortStrategy]="sortStrategy"></igx-column>
2277+
<igx-column field="UnitPrice" header="Unit Price" [dataType]="'number'" [sortable]="true"></igx-column>
2278+
<igx-column field="OrderDate" header="Order Date" [dataType]="'date'" [sortable]="true"></igx-column>
2279+
</igx-grid>
2280+
`,
2281+
standalone: true,
2282+
imports: [IgxGridComponent, IgxColumnComponent]
2283+
})
2284+
export class IgxGridFormattedValuesSortingComponent extends BasicGridComponent {
2285+
public override data = SampleTestData.gridProductData();
2286+
public sortStrategy = new FormattedValuesSortingStrategy();
2287+
2288+
public formatProductName = (value: string) => {
2289+
if (!value) {
2290+
return 'a';
2291+
}
2292+
const prefix = value.length > 10 ? 'a' : 'b';
2293+
return `${prefix}-${value}`;
2294+
}
2295+
2296+
public formatQuantity = (value: string) => {
2297+
if (!value) {
2298+
return 'c';
2299+
}
2300+
const prefix = value.length > 10 ? 'c' : 'd';
2301+
return `${prefix}-${value}`;
2302+
}
2303+
}
2304+
22692305
@Component({
22702306
template: `
22712307
<igx-grid #grid [data]="data" [height]="'500px'" [width]="'500px'">

0 commit comments

Comments
 (0)