Skip to content

Commit 650fdaa

Browse files
author
MPopov
committed
Merge remote-tracking branch 'IGX/bpenkov/fix-5764' into bpenkov/fix-5764
2 parents ac1ff16 + e72be95 commit 650fdaa

18 files changed

+319
-26
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
All notable changes for each version of this project will be documented in this file.
44

55
## 8.2.0
6-
76
### New theme
87
Ignite UI for angular now have a new theme that mimics Microsoft "Fluent" design system.
98
Depending on your use case you can use one of the following mixins:
@@ -31,6 +30,7 @@ For more information about the theming please read our [documentation](https://w
3130
- `IgxGrid`, `IgxTreeGrid`, `IgxHierarchicalGrid`
3231
- Advanced Filtering functionality is added. In the advanced filtering dialog, you could create groups of conditions across all grid columns. The advanced filtering button is shown in the grid's toolbar when `allowAdvancedFiltering` and `showToolbar` properties are set to `true`. You could also open/close the advanced filtering dialog using the `openAdvancedFilteringDialog` and `closeAdvancedFilteringDialog` methods.
3332
- `uniqueColumnValuesStrategy` input is added. This property provides a callback for loading unique column values on demand. If this property is provided, the unique values it generates will be used by the Excel Style Filtering (instead of using the unique values from the data that is bound to the grid).
33+
- `[filterStrategy] - input that allows you to override the default filtering strategy`
3434
- `igxExcelStyleLoading` directive is added, which can be used to provide a custom loading template for the Excel Style Filtering. If this property is not provided, a default loading template will be used instead.
3535
- introduced new properties `cellSelection` and `rowSelection` which accept GridSelection mode enumeration. Grid selection mode could be none, single or multiple. Also `hideRowSelectors` property is added, which allows you to show and hide row selectors when row selection is enabled.
3636
- introduced functionality for templating row and header selectors - [spec](https://github.com/IgniteUI/igniteui-angular/wiki/Row-Selection-Templating-(Grid-feature))

projects/igniteui-angular/src/lib/core/grid-selection.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,12 @@ export class IgxGridCRUDService {
151151
}
152152

153153
begin(cell): void {
154-
this.cell = this.createCell(cell);
155-
this.cell.primaryKey = this.primaryKey;
154+
const newCell = this.createCell(cell);
155+
newCell.primaryKey = this.primaryKey;
156156
const args = {
157-
cellID: this.cell.id,
158-
rowID: this.cell.id.rowID,
159-
oldValue: this.cell.value,
157+
cellID: newCell.id,
158+
rowID: newCell.id.rowID,
159+
oldValue: newCell.value,
160160
cancel: false
161161
};
162162

@@ -167,20 +167,22 @@ export class IgxGridCRUDService {
167167
return;
168168
}
169169

170-
171170
if (this.rowEditing) {
172-
if (!this.row) {
171+
if (this.row && !this.sameRow(newCell.id.rowID)) {
172+
this.grid.endEdit(true);
173+
this.cell = newCell;
173174
this.beginRowEdit();
174175
return;
175176
}
176177

177-
if (this.row && !this.sameRow(this.cell.id.rowID)) {
178-
this.grid.endEdit(true);
179-
this.cell = this.createCell(cell);
178+
this.cell = newCell;
179+
180+
if (!this.row) {
180181
this.beginRowEdit();
181182
return;
182183
}
183184
} else {
185+
this.cell = newCell;
184186
this.endRowEdit();
185187
}
186188
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ export abstract class BaseFilteringStrategy implements IFilteringStrategy {
5555
}
5656

5757
export class FilteringStrategy extends BaseFilteringStrategy {
58+
private static _instace: FilteringStrategy = null;
59+
60+
public constructor() { super(); }
61+
62+
public static instance() {
63+
return this._instace || (this._instace = new this());
64+
}
65+
5866
public filter<T>(data: T[], expressionsTree: IFilteringExpressionsTree, advancedExpressionsTree?: IFilteringExpressionsTree): T[] {
5967
let i;
6068
let rec;

projects/igniteui-angular/src/lib/grids/api.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export class GridBaseAPIService <T extends IgxGridBaseComponent & IGridDataBinda
117117

118118
public submit_value() {
119119
const cell = this.grid.crudService.cell;
120-
if (cell) {
120+
if (cell ) {
121121
const args = this.update_cell(cell, cell.editValue);
122122
if (args.cancel) {
123123
return;

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

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ import { IgxAdvancedFilteringDialogComponent } from './filtering/advanced-filter
9999
import { IgxColumnResizingService } from './grid-column-resizing.service';
100100
import { IgxHeadSelectorDirective, IgxRowSelectorDirective } from './igx-row-selectors.module';
101101
import { DeprecateProperty } from '../core/deprecateDecorators';
102+
import { IFilteringStrategy } from '../data-operations/filtering-strategy';
102103
import { IgxRowExpandedIndicatorDirective, IgxRowCollapsedIndicatorDirective,
103104
IgxHeaderExpandIndicatorDirective, IgxHeaderCollapseIndicatorDirective } from './grid/grid.directives';
104105
import { GridKeydownTargetType, GridSelectionMode, GridSummaryPosition, GridSummaryCalculationMode, FilterMode } from './common/enums';
@@ -242,6 +243,7 @@ export abstract class IgxGridBaseComponent extends DisplayDensityBase implements
242243
private _locale = null;
243244
public _destroyed = false;
244245
private overlayIDs = [];
246+
private _filteringStrategy: IFilteringStrategy;
245247

246248
private _hostWidth;
247249
private _advancedFilteringOverlayId: string;
@@ -1082,6 +1084,27 @@ export abstract class IgxGridBaseComponent extends DisplayDensityBase implements
10821084
}
10831085
}
10841086

1087+
/**
1088+
* Gets the filtering strategy of the grid.
1089+
* ```typescript
1090+
* let filterStrategy = this.grid.filterStrategy
1091+
* ```
1092+
*/
1093+
@Input()
1094+
get filterStrategy(): IFilteringStrategy {
1095+
return this._filteringStrategy;
1096+
}
1097+
1098+
/**
1099+
* Sets the filtering strategy of the grid.
1100+
* ```html
1101+
* <igx-grid #grid [data]="localData" [filterStrategy]="filterStrategy"></igx-grid>
1102+
* ```
1103+
*/
1104+
set filterStrategy(classRef: IFilteringStrategy) {
1105+
this._filteringStrategy = classRef;
1106+
}
1107+
10851108
/**
10861109
* An @Input property that provides a callback for loading unique column values on demand.
10871110
* If this property is provided, the unique values it generates will be used by the Excel Style Filtering.
@@ -3822,8 +3845,7 @@ export abstract class IgxGridBaseComponent extends DisplayDensityBase implements
38223845
}
38233846
this.gridAPI.escape_editMode();
38243847
}
3825-
3826-
this.notifyChanges();
3848+
this.cdr.detectChanges();
38273849
}
38283850
}
38293851
}
@@ -3849,7 +3871,7 @@ export abstract class IgxGridBaseComponent extends DisplayDensityBase implements
38493871
}
38503872
const row = new IgxRow(rowSelector, -1, this.gridAPI.getRowData(rowSelector));
38513873
this.gridAPI.update_row(row, value);
3852-
this.notifyChanges();
3874+
this.cdr.detectChanges();
38533875
}
38543876
}
38553877

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,46 @@ describe('IgxGrid - Cell Editing #grid', () => {
647647
expect(cell.editMode).toBe(true);
648648
});
649649

650+
it(`Should be able to update other cell in 'onCellEdit' event`, () => {
651+
grid.primaryKey = 'personNumber';
652+
fixture.detectChanges();
653+
654+
spyOn(grid.onCellEdit, 'emit').and.callThrough();
655+
grid.onCellEdit.subscribe((e: IGridEditEventArgs) => {
656+
if (e.cellID.columnID === 0) {
657+
grid.updateCell(1, e.rowID, 'age' );
658+
}
659+
});
660+
661+
let cell = grid.getCellByColumn(0, 'fullName');
662+
663+
UIInteractions.simulateClickAndSelectCellEvent(cell);
664+
fixture.detectChanges();
665+
666+
cell.nativeElement.dispatchEvent(new MouseEvent('dblclick'));
667+
fixture.detectChanges();
668+
669+
expect(cell.editMode).toBe(true);
670+
let editTemplate = fixture.debugElement.query(By.css('input'));
671+
UIInteractions.sendInput(editTemplate, 'New Name');
672+
fixture.detectChanges();
673+
674+
// press tab on edited cell
675+
UIInteractions.triggerKeyDownWithBlur('tab', cell.nativeElement, true);
676+
fixture.detectChanges();
677+
678+
expect(grid.onCellEdit.emit).toHaveBeenCalledTimes(2);
679+
cell = grid.getCellByColumn(0, 'age');
680+
expect(cell.editMode).toBe(true);
681+
expect(cell.value).toEqual(1);
682+
expect(cell.editValue).toEqual(1);
683+
editTemplate = fixture.debugElement.query(By.css('input'));
684+
expect(editTemplate.nativeElement.value).toEqual('1');
685+
686+
cell = grid.getCellByColumn(0, 'fullName');
687+
expect(cell.value).toEqual('New Name');
688+
});
689+
650690
it(`Should properly emit 'onCellEditCancel' event`, () => {
651691
spyOn(grid.onCellEditCancel, 'emit').and.callThrough();
652692
const cell = grid.getCellByColumn(0, 'fullName');

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

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ import {
4040
IgxTestExcelFilteringDatePickerComponent,
4141
IgxGridFilteringTemplateComponent,
4242
IgxGridFilteringESFTemplatesComponent,
43-
IgxGridFilteringESFLoadOnDemandComponent
43+
IgxGridFilteringESFLoadOnDemandComponent,
44+
CustomFilteringStrategyComponent
4445
} from '../../test-utils/grid-samples.spec';
4546
import { HelperUtils, resizeObserverIgnoreError } from '../../test-utils/helper-utils.spec';
4647
import { GridSelectionMode, FilterMode } from '../common/enums';
@@ -3601,7 +3602,8 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => {
36013602
IgxTestExcelFilteringDatePickerComponent,
36023603
IgxGridFilteringESFTemplatesComponent,
36033604
IgxGridFilteringESFLoadOnDemandComponent,
3604-
IgxGridFilteringMCHComponent
3605+
IgxGridFilteringMCHComponent,
3606+
CustomFilteringStrategyComponent
36053607
],
36063608
imports: [
36073609
NoopAnimationsModule,
@@ -5843,6 +5845,97 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => {
58435845
GridFunctions.verifyColumnIsPinned(column, true, 8);
58445846
}));
58455847
});
5848+
describe('IgxGrid - Custom Filtering Strategy #grid', () => {
5849+
let fix;
5850+
let grid;
5851+
5852+
beforeEach(async(() => {
5853+
resizeObserverIgnoreError();
5854+
fix = TestBed.createComponent(CustomFilteringStrategyComponent);
5855+
grid = fix.componentInstance.grid;
5856+
fix.detectChanges();
5857+
}));
5858+
5859+
it('Should be able to set custom filtering strategy', () => {
5860+
expect(grid.filterStrategy).toBeUndefined();
5861+
grid.filterStrategy = fix.componentInstance.strategy;
5862+
fix.detectChanges();
5863+
5864+
expect(grid.filterStrategy).toEqual(fix.componentInstance.strategy);
5865+
});
5866+
5867+
it('Should be able to override getFieldValue method', fakeAsync(() => {
5868+
GridFunctions.clickFilterCellChip(fix, 'Name'); // Name column contains nasted object as a vulue
5869+
fix.detectChanges();
5870+
GridFunctions.typeValueInFilterRowInput('ca', fix);
5871+
tick(50);
5872+
GridFunctions.submitFilterRowInput(fix);
5873+
tick(50);
5874+
fix.detectChanges();
5875+
5876+
expect(grid.filteredData).toEqual([]);
5877+
GridFunctions.resetFilterRow(fix);
5878+
GridFunctions.closeFilterRow(fix);
5879+
fix.detectChanges();
5880+
5881+
// Apply the custom strategy and perform the same filter
5882+
grid.filterStrategy = fix.componentInstance.strategy;
5883+
fix.detectChanges();
5884+
GridFunctions.clickFilterCellChip(fix, 'Name');
5885+
fix.detectChanges();
5886+
GridFunctions.typeValueInFilterRowInput('ca', fix);
5887+
tick(50);
5888+
GridFunctions.submitFilterRowInput(fix);
5889+
tick(50);
5890+
fix.detectChanges();
5891+
5892+
expect(grid.filteredData).toEqual(
5893+
[{ ID: 1, Name: { FirstName: 'Casey', LastName: 'Houston' }, JobTitle: 'Vice President', Company: 'Company A' }]);
5894+
}));
5895+
5896+
it('Should be able to override findMatchByExpression method', fakeAsync(() => {
5897+
GridFunctions.clickFilterCellChip(fix, 'JobTitle'); // Default strategy is case not sensitive
5898+
fix.detectChanges();
5899+
GridFunctions.typeValueInFilterRowInput('direct', fix);
5900+
tick(50);
5901+
GridFunctions.submitFilterRowInput(fix);
5902+
tick(50);
5903+
fix.detectChanges();
5904+
5905+
expect(grid.filteredData).toEqual([
5906+
{ ID: 2, Name: { FirstName: 'Gilberto', LastName: 'Todd' } , JobTitle: 'Director', Company: 'Company C' },
5907+
{ ID: 3, Name: { FirstName: 'Tanya', LastName: 'Bennett' } , JobTitle: 'Director', Company: 'Company A' }]);
5908+
GridFunctions.resetFilterRow(fix);
5909+
GridFunctions.closeFilterRow(fix);
5910+
fix.detectChanges();
5911+
5912+
// Apply the custom strategy and perform the same filter
5913+
grid.filterStrategy = fix.componentInstance.strategy;
5914+
fix.detectChanges();
5915+
GridFunctions.clickFilterCellChip(fix, 'JobTitle');
5916+
fix.detectChanges();
5917+
GridFunctions.typeValueInFilterRowInput('direct', fix);
5918+
tick(50);
5919+
GridFunctions.submitFilterRowInput(fix);
5920+
tick(50);
5921+
fix.detectChanges();
5922+
5923+
expect(grid.filteredData).toEqual([]);
5924+
}));
5925+
5926+
it('should use the custom filtering stategy when filter the grid through API method', fakeAsync(() => {
5927+
grid.filterStrategy = fix.componentInstance.strategy;
5928+
fix.detectChanges();
5929+
grid.filter('Name', 'D', IgxStringFilteringOperand.instance().condition('contains'));
5930+
tick(30);
5931+
fix.detectChanges();
5932+
5933+
expect(grid.filteredData).toEqual([
5934+
{ ID: 7, Name: { FirstName: 'Debra', LastName: 'Morton' } ,
5935+
JobTitle: 'Associate Software Developer', Company: 'Company B' },
5936+
{ ID: 10, Name: { FirstName: 'Eduardo', LastName: 'Ramirez' }, JobTitle: 'Manager', Company: 'Company E' }]);
5937+
}));
5938+
});
58465939
});
58475940

58485941
const expectedResults = [];

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1809,6 +1809,33 @@ describe('IgxGrid - Row Editing #grid', () => {
18091809
cancel: false
18101810
});
18111811
}));
1812+
1813+
it(`Should properly emit 'onCellEdit' event `, fakeAsync(() => {
1814+
spyOn(grid.onCellEdit, 'emit').and.callThrough();
1815+
spyOn(grid.onRowEdit, 'emit').and.callThrough();
1816+
1817+
let cell = grid.getCellByColumn(0, 'ProductName');
1818+
const cellArgs = { cellID: cell.cellID, rowID: cell.row.rowID, oldValue: 'Chai', newValue: 'New Value', cancel: false };
1819+
1820+
cell.nativeElement.dispatchEvent(new MouseEvent('dblclick'));
1821+
tick(16);
1822+
fix.detectChanges();
1823+
1824+
expect(cell.editMode).toBe(true);
1825+
const editTemplate = fix.debugElement.query(By.css('input'));
1826+
UIInteractions.sendInput(editTemplate, 'New Value');
1827+
fix.detectChanges();
1828+
1829+
// Click on cell in different row
1830+
cell = grid.getCellByColumn(2, 'ProductName');
1831+
UIInteractions.simulateClickAndSelectCellEvent(cell);
1832+
tick(16);
1833+
fix.detectChanges();
1834+
1835+
expect(grid.onRowEdit.emit).toHaveBeenCalledTimes(1);
1836+
expect(grid.onCellEdit.emit).toHaveBeenCalledTimes(1);
1837+
expect(grid.onCellEdit.emit).toHaveBeenCalledWith(cellArgs);
1838+
}));
18121839
});
18131840

18141841
describe('Column editable property', () => {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,12 +1240,12 @@ describe('IgxGrid - Row Selection #grid', () => {
12401240
});
12411241

12421242
it('Should be able to update row through primaryKey', () => {
1243-
spyOn(grid.cdr, 'markForCheck').and.callThrough();
1243+
spyOn(grid.onRowEdit, 'emit').and.callThrough();
12441244
expect(grid.primaryKey).toBeTruthy();
12451245
expect(grid.rowList.length).toEqual(10, 'All 10 rows should initialized');
12461246
expect(grid.getRowByKey(2).rowData['JobTitle']).toMatch('Director');
12471247
grid.updateRow({ ID: 2, Name: 'Gilberto Todd', JobTitle: 'Vice President' }, 2);
1248-
expect(grid.cdr.markForCheck).toHaveBeenCalledTimes(1);
1248+
expect(grid.onRowEdit.emit).toHaveBeenCalledTimes(1);
12491249
fix.detectChanges();
12501250
expect(grid.getRowByIndex(1).rowData['JobTitle']).toMatch('Vice President');
12511251
expect(grid.getRowByKey(2).rowData['JobTitle']).toMatch('Vice President');

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
<ng-template igxGridFor let-rowData [igxGridForOf]="data
108108
| gridTransaction:id:pipeTrigger
109109
| visibleColumns:hasVisibleColumns
110-
| gridFiltering:filteringExpressionsTree:advancedFilteringExpressionsTree:id:pipeTrigger
110+
| gridFiltering:filteringExpressionsTree:filterStrategy:advancedFilteringExpressionsTree:id:pipeTrigger
111111
| gridSort:sortingExpressions:id:pipeTrigger
112112
| gridGroupBy:groupingExpressions:groupingExpansionState:groupsExpanded:id:groupsRecords:pipeTrigger
113113
| gridPaging:page:perPage:id:pipeTrigger

0 commit comments

Comments
 (0)