Skip to content
Merged
41 changes: 25 additions & 16 deletions projects/igniteui-angular/grids/core/src/state-base.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,11 @@ export class IgxGridStateBaseDirective {
private FEATURES = {
sorting: {
getFeatureState: (context: IgxGridStateBaseDirective): IGridState => {
const sortingState = context.currGrid.sortingExpressions;
sortingState.forEach(s => {
delete s.strategy;
delete s.owner;
const sortingState = context.currGrid.sortingExpressions.map(s => {
const copy = { ...s };
delete copy.strategy;
delete copy.owner;
return copy;
});
return { sorting: sortingState };
},
Expand All @@ -154,10 +155,14 @@ export class IgxGridStateBaseDirective {
getFeatureState: (context: IgxGridStateBaseDirective): IGridState => {
const filteringState = context.currGrid.filteringExpressionsTree;
if (filteringState) {
delete filteringState.owner;
for (const item of filteringState.filteringOperands) {
delete (item as IFilteringExpressionsTree).owner;
}
const copy: IFilteringExpressionsTree = { ...filteringState };
delete (copy as any).owner;
copy.filteringOperands = filteringState.filteringOperands.map(item => {
const operandCopy = { ...(item as IFilteringExpressionsTree) };
delete (operandCopy as any).owner;
return operandCopy;
});
Comment thread
viktorkombov marked this conversation as resolved.
Outdated
return { filtering: copy };
}
return { filtering: filteringState };
},
Expand All @@ -171,11 +176,14 @@ export class IgxGridStateBaseDirective {
const filteringState = context.currGrid.advancedFilteringExpressionsTree;
let advancedFiltering: any;
if (filteringState) {
delete filteringState.owner;
for (const item of filteringState.filteringOperands) {
delete (item as IFilteringExpressionsTree).owner;
}
advancedFiltering = filteringState;
const copy: IFilteringExpressionsTree = { ...filteringState };
delete (copy as any).owner;
copy.filteringOperands = filteringState.filteringOperands.map(item => {
const operandCopy = { ...(item as IFilteringExpressionsTree) };
delete (operandCopy as any).owner;
return operandCopy;
});
Comment thread
viktorkombov marked this conversation as resolved.
Outdated
advancedFiltering = copy;
} else {
advancedFiltering = {};
}
Expand Down Expand Up @@ -299,9 +307,10 @@ export class IgxGridStateBaseDirective {
groupBy: {
getFeatureState: (context: IgxGridStateBaseDirective): IGridState => {
const grid = context.currGrid;
const groupingExpressions = grid.groupingExpressions;
groupingExpressions.forEach(expr => {
delete expr.strategy;
const groupingExpressions = grid.groupingExpressions.map(expr => {
const copy = { ...expr };
delete copy.strategy;
Comment thread
viktorkombov marked this conversation as resolved.
return copy;
});
const expansionState = grid.groupingExpansionState;
const groupsExpanded = grid.groupsExpanded;
Expand Down
64 changes: 64 additions & 0 deletions projects/igniteui-angular/grids/core/src/state.directive.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,70 @@ describe('IgxGridState - input properties #grid', () => {
expect(prodIdColumn.colEnd).toBe(1);
});

it('getState should not mutate live sorting expressions (strategy/owner)', () => {
const fix = TestBed.createComponent(IgxGridStateComponent);
fix.detectChanges();
const grid = fix.componentInstance.grid;
const state = fix.componentInstance.state;

const customStrategy = DefaultSortingStrategy.instance();
grid.sortingExpressions = [
{ fieldName: 'ProductID', dir: SortingDirection.Asc, ignoreCase: false, strategy: customStrategy }
];
fix.detectChanges();

expect(grid.sortingExpressions[0].strategy).toBe(customStrategy, 'strategy should be set before getState');

state.getState(false, 'sorting');

expect(grid.sortingExpressions[0].strategy).toBe(customStrategy, 'strategy should not be removed from live expressions after getState');
Comment thread
viktorkombov marked this conversation as resolved.
});

it('getState should not mutate live groupBy expressions (strategy)', () => {
const fix = TestBed.createComponent(IgxGridStateComponent);
fix.detectChanges();
Comment thread
viktorkombov marked this conversation as resolved.
const grid = fix.componentInstance.grid;
const state = fix.componentInstance.state;

const customStrategy = DefaultSortingStrategy.instance();
grid.groupingExpressions = [
{ fieldName: 'ProductID', dir: SortingDirection.Asc, ignoreCase: false, strategy: customStrategy }
];
fix.detectChanges();

expect(grid.groupingExpressions[0].strategy).toBe(customStrategy, 'strategy should be set before getState');

state.getState(false, 'groupBy');

Comment thread
viktorkombov marked this conversation as resolved.
Outdated
expect(grid.groupingExpressions[0].strategy).toBe(customStrategy, 'strategy should not be removed from live groupBy expressions after getState');
});

it('getState should not mutate live filtering expressions (owner)', () => {
const fix = TestBed.createComponent(IgxGridStateComponent);
fix.detectChanges();
const grid = fix.componentInstance.grid;
const state = fix.componentInstance.state;

const filteringTree = new FilteringExpressionsTree(FilteringLogic.And);
const productFilteringTree = new FilteringExpressionsTree(FilteringLogic.And, 'ProductName');
productFilteringTree.filteringOperands.push({
condition: IgxBooleanFilteringOperand.instance().condition('true'),
conditionName: 'true',
fieldName: 'InStock',
ignoreCase: true
});
filteringTree.filteringOperands.push(productFilteringTree);
(filteringTree as any).owner = 'testOwner';
grid.filteringExpressionsTree = filteringTree;
fix.detectChanges();

expect((grid.filteringExpressionsTree as any).owner).toBe('testOwner', 'owner should be set before getState');

state.getState(false, 'filtering');

expect((grid.filteringExpressionsTree as any).owner).toBe('testOwner', 'owner should not be removed from live filtering tree after getState');
Comment thread
viktorkombov marked this conversation as resolved.
Outdated
});

it('should preserve column widths when restoring state with all columns hidden', () => {
const fix = TestBed.createComponent(IgxGridStateComponent);
fix.detectChanges();
Expand Down
Loading