Skip to content

Commit

Permalink
feat(grid): expose input to set sort strategy 6.1.x #2734
Browse files Browse the repository at this point in the history
  • Loading branch information
hanastasov committed Oct 31, 2018
1 parent 43d8c0c commit 9b9c66a
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 27 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes for each version of this project will be documented in this

## 6.1.8

### General

- `sortStrategy` input exposed to provide custom sort strategy for the `IgxColumnComponent`. The custom strategy should implement the `ISortingStrategy` interface, or can extend the base `SortingStrategy` class and override all or some of its public/protected members.

### Bug fixes

- Fix sorting and groupby expression not syncing when there are already sorted columns. #2786
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ISortingStrategy } from './sorting-strategy';

/**
* Represents sorting expressions.
*/
Expand All @@ -11,4 +13,5 @@ export interface ISortingExpression {
fieldName: string;
dir: SortingDirection;
ignoreCase?: boolean;
strategy?: ISortingStrategy;
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,18 @@ export class SortingStrategy implements ISortingStrategy {
}
return a > b ? 1 : a < b ? -1 : 0;
}
protected compareObjects(obj1: object, obj2: object, key: string, reverse: number, ignoreCase: boolean) {
protected compareObjects(obj1: object, obj2: object, key: string, reverse: number, ignoreCase: boolean, strategy: ISortingStrategy) {
let a = obj1[key];
let b = obj2[key];
if (ignoreCase) {
a = a && a.toLowerCase ? a.toLowerCase() : a;
b = b && b.toLowerCase ? b.toLowerCase() : b;
}
return reverse * this.compareValues(a, b);
if (strategy) {
return reverse * strategy.compareValues(a, b);
} else {
return reverse * this.compareValues(a, b);
}
}
protected arraySort<T>(data: T[], compareFn?): T[] {
return data.sort(compareFn);
Expand Down Expand Up @@ -78,7 +82,7 @@ export class SortingStrategy implements ISortingStrategy {
false;
const reverse = (expression.dir === SortingDirection.Desc ? -1 : 1);
const cmpFunc = (obj1, obj2) => {
return this.compareObjects(obj1, obj2, key, reverse, ignoreCase);
return this.compareObjects(obj1, obj2, key, reverse, ignoreCase, expression.strategy);
};
return this.arraySort(data, cmpFunc);
}
Expand Down
21 changes: 15 additions & 6 deletions projects/igniteui-angular/src/lib/grid/api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { IgxColumnComponent } from './column.component';
import { IGridEditEventArgs, IgxGridComponent } from './grid.component';
import { IgxGridRowComponent } from './row.component';
import { IFilteringOperation, FilteringExpressionsTree, IFilteringExpressionsTree } from '../../public_api';
import { ISortingStrategy } from '../data-operations/sorting-strategy';
import { SortingStateDefaults } from '../data-operations/sorting-state.interface';
/**
*@hidden
*/
Expand Down Expand Up @@ -207,13 +209,13 @@ export class IgxGridAPIService {
}
}

public sort(id: string, fieldName: string, dir: SortingDirection, ignoreCase: boolean): void {
public sort(id: string, fieldName: string, dir: SortingDirection, ignoreCase: boolean, strategy: ISortingStrategy): void {
if (dir === SortingDirection.None) {
this.remove_grouping_expression(id, fieldName);
}
const sortingState = cloneArray(this.get(id).sortingExpressions);

this.prepare_sorting_expression([sortingState], { fieldName, dir, ignoreCase });
strategy = strategy ? strategy : this.getSortStrategyPerColumn(id, fieldName);
this.prepare_sorting_expression([sortingState], { fieldName, dir, ignoreCase, strategy });
this.get(id).sortingExpressions = sortingState;
}

Expand All @@ -224,17 +226,18 @@ export class IgxGridAPIService {
if (each.dir === SortingDirection.None) {
this.remove_grouping_expression(id, each.fieldName);
}
each.strategy = each.strategy ? each.strategy : this.getSortStrategyPerColumn(id, each.fieldName);
this.prepare_sorting_expression([sortingState], each);
}

this.get(id).sortingExpressions = sortingState;
}

public groupBy(id: string, fieldName: string, dir: SortingDirection, ignoreCase: boolean): void {
public groupBy(id: string, fieldName: string, dir: SortingDirection, ignoreCase: boolean, strategy: ISortingStrategy): void {
const groupingState = cloneArray(this.get(id).groupingExpressions);
const sortingState = cloneArray(this.get(id).sortingExpressions);

this.prepare_sorting_expression([sortingState, groupingState], { fieldName, dir, ignoreCase });
strategy = strategy ? strategy : this.getSortStrategyPerColumn(id, fieldName);
this.prepare_sorting_expression([sortingState, groupingState], { fieldName, dir, ignoreCase, strategy });
this.get(id).groupingExpressions = groupingState;
this.arrange_sorting_expressions(id);
}
Expand All @@ -244,6 +247,7 @@ export class IgxGridAPIService {
const sortingState = cloneArray(this.get(id).sortingExpressions);

for (const each of expressions) {
each.strategy = each.strategy ? each.strategy : this.getSortStrategyPerColumn(id, each.fieldName);
this.prepare_sorting_expression([sortingState, groupingState], each);
}

Expand Down Expand Up @@ -476,4 +480,9 @@ export class IgxGridAPIService {
groupingExpressions.splice(index, 1);
}
}

protected getSortStrategyPerColumn(id: string, fieldName: string) {
return this.get_column_by_name(this.get(id).id, fieldName) ?
this.get_column_by_name(id, fieldName).sortStrategy : undefined;
}
}
30 changes: 30 additions & 0 deletions projects/igniteui-angular/src/lib/grid/column.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
} from '../../public_api';
import { IgxGridHeaderComponent } from './grid-header.component';
import { valToPxlsUsingRange } from '../core/utils';
import { SortingStrategy } from '../data-operations/sorting-strategy';

/**
* **Ignite UI for Angular Column** -
Expand Down Expand Up @@ -468,6 +469,31 @@ export class IgxColumnComponent implements AfterContentInit {
public set filters(classRef: any) {
this._filters = classRef;
}
/**
* Gets the column `sortStrategy`.
* ```typescript
* let sortStrategy = this.column.sortStrategy'
* ```
* @memberof IgxColumnComponent
*/
@Input()
public get sortStrategy(): any {
return this._sortStrategy;
}
/**
* Sets the column `sortStrategy`.
* ```typescript
* this.column.sortStrategy = new CustomSortingStrategy().
*
* class CustomSortingStrategy extends SortingStrategy {
* ...
* }
* ```
* @memberof IgxColumnComponent
*/
public set sortStrategy(classRef: any) {
this._sortStrategy = classRef;
}
/**
* Gets the default minimum `width` of the column.
* ```typescript
Expand Down Expand Up @@ -715,6 +741,10 @@ export class IgxColumnComponent implements AfterContentInit {
*@hidden
*/
protected _filters = null;
/**
*@hidden
*/
protected _sortStrategy = new SortingStrategy();
/**
*@hidden
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,13 @@ export class IgxGridHeaderComponent implements OnInit, DoCheck, AfterViewInit {
this.sortDirection + 1 > SortingDirection.Desc ? SortingDirection.Asc : SortingDirection.Desc
: this.sortDirection + 1 > SortingDirection.Desc ? SortingDirection.None : this.sortDirection + 1;
this.sortDirection = sortDir;
this.grid.sort({ fieldName: this.column.field, dir: this.sortDirection, ignoreCase: this.column.sortingIgnoreCase });
this.grid.sort({ fieldName: this.column.field, dir: this.sortDirection, ignoreCase: this.column.sortingIgnoreCase,
strategy: this.column.sortStrategy });
this.grid.onSortingDone.emit({
dir: this.sortDirection,
fieldName: this.column.field,
ignoreCase: this.column.sortingIgnoreCase
ignoreCase: this.column.sortingIgnoreCase,
strategy: this.column.sortStrategy
});
}
}
Expand Down
3 changes: 2 additions & 1 deletion projects/igniteui-angular/src/lib/grid/grid.common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,8 @@ export class IgxGroupAreaDropDirective extends IgxDropDirective {
const column: IgxColumnComponent = drag.column;
const isGrouped = column.grid.groupingExpressions.findIndex((item) => item.fieldName === column.field) !== -1;
if (column.groupable && !isGrouped) {
column.grid.groupBy({ fieldName: column.field, dir: SortingDirection.Asc, ignoreCase: column.sortingIgnoreCase });
column.grid.groupBy({ fieldName: column.field, dir: SortingDirection.Asc, ignoreCase: column.sortingIgnoreCase,
strategy: column.sortStrategy });
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions projects/igniteui-angular/src/lib/grid/grid.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3423,7 +3423,7 @@ export class IgxGridComponent implements OnInit, OnDestroy, AfterContentInit, Af
* @hidden
*/
protected _sort(expression: ISortingExpression) {
this.gridAPI.sort(this.id, expression.fieldName, expression.dir, expression.ignoreCase);
this.gridAPI.sort(this.id, expression.fieldName, expression.dir, expression.ignoreCase, expression.strategy);
}

/**
Expand All @@ -3437,7 +3437,7 @@ export class IgxGridComponent implements OnInit, OnDestroy, AfterContentInit, Af
* @hidden
*/
protected _groupBy(expression: ISortingExpression) {
this.gridAPI.groupBy(this.id, expression.fieldName, expression.dir, expression.ignoreCase);
this.gridAPI.groupBy(this.id, expression.fieldName, expression.dir, expression.ignoreCase, expression.strategy);
}

/**
Expand Down
29 changes: 19 additions & 10 deletions projects/igniteui-angular/src/lib/grid/grid.groupby.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { IgxGridRowComponent } from './row.component';
import { IgxChipComponent } from '../chips/chip.component';
import { wait, UIInteractions } from '../test-utils/ui-interactions.spec';
import { HelperUtils} from '../test-utils/helper-utils.spec';
import { SortingStrategy } from '../data-operations/sorting-strategy';
import { SortingStateDefaults } from '../data-operations/sorting-state.interface';

describe('IgxGrid - GroupBy', () => {
const COLUMN_HEADER_CLASS = '.igx-grid__th';
Expand Down Expand Up @@ -1916,45 +1918,49 @@ describe('IgxGrid - GroupBy', () => {
it('should update grouping expression when sorting a column first then grouping by it and changing sorting for it again', () => {
const fix = TestBed.createComponent(DefaultGridComponent);
const grid = fix.componentInstance.instance;
let strategy = new CustomSortingStrategy();
fix.componentInstance.enableSorting = true;
fix.detectChanges();

grid.sort({ fieldName: 'ID', dir: SortingDirection.Asc, ignoreCase: false });
grid.sort({ fieldName: 'ID', dir: SortingDirection.Asc, ignoreCase: false, strategy: new CustomSortingStrategy() });

expect(grid.sortingExpressions).toEqual([{ fieldName: 'ID', dir: SortingDirection.Asc, ignoreCase: false }]);
expect(grid.sortingExpressions).toEqual([{ fieldName: 'ID', dir: SortingDirection.Asc, ignoreCase: false, strategy: strategy }]);
expect(grid.groupingExpressions).toEqual([]);

strategy = SortingStateDefaults.strategy;
grid.groupBy({ fieldName: 'ID', dir: SortingDirection.Asc, ignoreCase: false });
grid.sort({ fieldName: 'ID', dir: SortingDirection.Desc, ignoreCase: false });

expect(grid.sortingExpressions).toEqual([{ fieldName: 'ID', dir: SortingDirection.Desc, ignoreCase: false }]);
expect(grid.groupingExpressions).toEqual([{ fieldName: 'ID', dir: SortingDirection.Desc, ignoreCase: false }]);
expect(grid.sortingExpressions).toEqual([{ fieldName: 'ID', dir: SortingDirection.Desc, ignoreCase: false, strategy: strategy }]);
expect(grid.groupingExpressions).toEqual([{ fieldName: 'ID', dir: SortingDirection.Desc, ignoreCase: false, strategy: strategy }]);
});

it('should update grouping expression when sorting a column first then grouping by another and changing sorting for it', () => {
const fix = TestBed.createComponent(DefaultGridComponent);
const grid = fix.componentInstance.instance;
const strategy = SortingStateDefaults.strategy;
fix.componentInstance.enableSorting = true;
fix.detectChanges();

grid.sort({ fieldName: 'Downloads', dir: SortingDirection.Asc, ignoreCase: false });
grid.sort({ fieldName: 'ID', dir: SortingDirection.Desc, ignoreCase: false });

expect(grid.sortingExpressions).toEqual([
{ fieldName: 'Downloads', dir: SortingDirection.Asc, ignoreCase: false },
{ fieldName: 'ID', dir: SortingDirection.Desc, ignoreCase: false }
{ fieldName: 'Downloads', dir: SortingDirection.Asc, ignoreCase: false, strategy: strategy },
{ fieldName: 'ID', dir: SortingDirection.Desc, ignoreCase: false, strategy: strategy }
]);
expect(grid.groupingExpressions).toEqual([]);

grid.groupBy({ fieldName: 'Released', dir: SortingDirection.Asc, ignoreCase: false });
grid.sort({ fieldName: 'Released', dir: SortingDirection.Desc, ignoreCase: false });

expect(grid.sortingExpressions).toEqual([
{ fieldName: 'Released', dir: SortingDirection.Desc, ignoreCase: false },
{ fieldName: 'Downloads', dir: SortingDirection.Asc, ignoreCase: false },
{ fieldName: 'ID', dir: SortingDirection.Desc, ignoreCase: false }
{ fieldName: 'Released', dir: SortingDirection.Desc, ignoreCase: false, strategy: strategy },
{ fieldName: 'Downloads', dir: SortingDirection.Asc, ignoreCase: false, strategy: strategy },
{ fieldName: 'ID', dir: SortingDirection.Desc, ignoreCase: false, strategy: strategy }
]);
expect(grid.groupingExpressions).toEqual([{ fieldName: 'Released', dir: SortingDirection.Desc, ignoreCase: false }]);
expect(grid.groupingExpressions).toEqual([{ fieldName: 'Released', dir: SortingDirection.Desc, ignoreCase: false,
strategy: strategy }]);
});

function sendInput(element, text, fix) {
Expand Down Expand Up @@ -2155,3 +2161,6 @@ export class GroupByDataMoreColumnsComponent extends DataParent {
@ViewChild(IgxGridComponent, { read: IgxGridComponent })
public instance: IgxGridComponent;
}

export class CustomSortingStrategy extends SortingStrategy {
}
11 changes: 8 additions & 3 deletions projects/igniteui-angular/src/lib/grid/grid.pipes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { cloneArray } from '../core/utils';
import { DataUtil } from '../data-operations/data-util';
import { FilteringLogic, IFilteringExpression } from '../data-operations/filtering-expression.interface';
import { IGroupByExpandState } from '../data-operations/groupby-expand-state.interface';
import { IGroupByResult } from '../data-operations/sorting-strategy';
import { IGroupByResult, ISortingStrategy } from '../data-operations/sorting-strategy';
import { IFilteringExpressionsTree } from '../data-operations/filtering-expressions-tree';
import { ISortingExpression } from '../data-operations/sorting-expression.interface';
import { IgxGridAPIService } from './api.service';
Expand All @@ -22,14 +22,19 @@ export class IgxGridSortingPipe implements PipeTransform {

public transform(collection: any[], expressions: ISortingExpression | ISortingExpression[],
id: string, pipeTrigger: number): any[] {

const state = { expressions: [] };
let strategy: ISortingStrategy;
const state = { expressions: [], strategy };
state.expressions = this.gridAPI.get(id).sortingExpressions;

if (!state.expressions.length) {
return collection;
}

// DataUtil.sort needs a sorting strategy to start with, so it makes sense to start with the strategy from the first expression
// sorting-strategy.ts, sortDataRecursive method then takes care and use the corresponding strategy for each expression
strategy = expressions[0].strategy;
state.strategy = strategy;

return DataUtil.sort(cloneArray(collection), state);
}
}
Expand Down

0 comments on commit 9b9c66a

Please sign in to comment.