Skip to content

Commit 8d17715

Browse files
committed
Merge remote-tracking branch 'origin/master' into mdragnev/row-pinning-summaries
2 parents 5cd583a + ab91892 commit 8d17715

File tree

5 files changed

+131
-25
lines changed

5 files changed

+131
-25
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ export class GridBaseAPIService <T extends IgxGridBaseDirective & GridType> {
8686
}
8787

8888
public get_row_by_key(rowSelector: any): IgxRowDirective<IgxGridBaseDirective & GridType> {
89+
if (!this.grid) {
90+
return null;
91+
}
8992
const primaryKey = this.grid.primaryKey;
9093
if (primaryKey !== undefined && primaryKey !== null) {
9194
return this.grid.dataRowList.find((row) => row.rowData[primaryKey] === rowSelector);

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

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1747,8 +1747,8 @@ export class IgxGridBaseDirective extends DisplayDensityBase implements
17471747
/**
17481748
* @hidden @internal
17491749
*/
1750-
@ViewChild('pinContainer', { static: false })
1751-
public pinContainer: ElementRef;
1750+
@ViewChildren('pinContainer', { read: ElementRef })
1751+
public pinContainers: QueryList<ElementRef>;
17521752

17531753
/**
17541754
* @hidden @internal
@@ -2410,6 +2410,9 @@ export class IgxGridBaseDirective extends DisplayDensityBase implements
24102410
*/
24112411
protected destroy$ = new Subject<any>();
24122412

2413+
protected _filteredPinnedData;
2414+
protected _filteredUnpinnedData;
2415+
24132416
/**
24142417
* @hidden
24152418
*/
@@ -2869,6 +2872,17 @@ export class IgxGridBaseDirective extends DisplayDensityBase implements
28692872
}
28702873
}
28712874

2875+
public setFilterData(data, pinned: boolean) {
2876+
if (this.hasPinnedRecords && pinned) {
2877+
this._filteredPinnedData = data;
2878+
this.filteredData = [... this._filteredPinnedData, ... this._filteredUnpinnedData];
2879+
} else if (this.hasPinnedRecords && !pinned) {
2880+
this._filteredUnpinnedData = data;
2881+
} else {
2882+
this.filteredData = data;
2883+
}
2884+
}
2885+
28722886
/**
28732887
* @hidden
28742888
* @internal
@@ -2960,6 +2974,12 @@ export class IgxGridBaseDirective extends DisplayDensityBase implements
29602974
vertScrDC.addEventListener('scroll', this.scrollHandler);
29612975
vertScrDC.addEventListener('wheel', () => this.wheelHandler());
29622976

2977+
this.pinContainers.changes.subscribe((c) => {
2978+
if (this.hasPinnedRecords) {
2979+
// on row pin containers change grid sizes should be recalculated.
2980+
this.calculateGridSizes();
2981+
}
2982+
});
29632983
}
29642984

29652985
/**
@@ -4144,8 +4164,9 @@ export class IgxGridBaseDirective extends DisplayDensityBase implements
41444164
}
41454165

41464166
get pinnedRowHeight() {
4147-
const containerHeight = this.pinContainer ? this.pinContainer.nativeElement.offsetHeight : 0;
4148-
return this._pinnedRecordIDs.length > 0 ? containerHeight : 0;
4167+
const pinContainer = this.pinContainers && this.pinContainers.length > 0 ? this.pinContainers.first : null;
4168+
const containerHeight = pinContainer ? pinContainer.nativeElement.offsetHeight : 0;
4169+
return this.hasPinnedRecords ? containerHeight : 0;
41494170
}
41504171

41514172
get totalHeight() {

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

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -108,22 +108,29 @@
108108
<span *ngIf="hasMovableColumns && draggedColumn && pinnedColumns.length > 0"
109109
[igxColumnMovingDrop]="headerContainer" [attr.droppable]="true" id="left"
110110
class="igx-grid__scroll-on-drag-pinned" [style.left.px]="pinnedWidth"></span>
111-
<ng-template #pinnedRecordsTemplate>
112-
<ng-container *ngFor="let rowData of data
113-
| gridTransaction:id:pipeTrigger
114-
| visibleColumns:hasVisibleColumns
115-
| rowPinning:id:true:pipeTrigger
116-
| gridFiltering:filteringExpressionsTree:filterStrategy:advancedFilteringExpressionsTree:id:pipeTrigger:filteringPipeTrigger
117-
| gridSort:sortingExpressions:sortStrategy:id:pipeTrigger
118-
| gridDetails:hasDetails:expansionStates:pipeTrigger; let rowIndex = index">
119-
<ng-container *ngTemplateOutlet="getRowTemplate(rowData); context: getContext(rowData, rowIndex, true)">
111+
<ng-container *ngTemplateOutlet="hasPinnedRecords && isRowPinningToTop ? pinnedRecordsTemplate : null">
112+
</ng-container>
113+
<ng-template #pinnedRecordsTemplate>
114+
<ng-container *ngIf='data
115+
| gridTransaction:id:pipeTrigger
116+
| visibleColumns:hasVisibleColumns
117+
| rowPinning:id:true:pipeTrigger
118+
| gridFiltering:filteringExpressionsTree:filterStrategy:advancedFilteringExpressionsTree:id:pipeTrigger:filteringPipeTrigger:true
119+
| gridSort:sortingExpressions:sortStrategy:id:pipeTrigger
120+
| gridDetails:hasDetails:expansionStates:pipeTrigger as pinnedData'>
121+
<div #pinContainer *ngIf='pinnedData.length > 0'
122+
[ngClass]="{
123+
'igx-grid__tr--pinned-bottom': !isRowPinningToTop,
124+
'igx-grid__tr--pinned-top': isRowPinningToTop
125+
}"
126+
class='igx-grid__tr--pinned' [style.bottom.px]=' !isRowPinningToTop ? pinnedBottom : null'>
127+
<ng-container *ngFor="let rowData of pinnedData; let rowIndex = index">
128+
<ng-container *ngTemplateOutlet="getRowTemplate(rowData); context: getContext(rowData, rowIndex, true)">
129+
</ng-container>
120130
</ng-container>
121-
</ng-container>
122-
</ng-template>
123-
<div #pinContainer *ngIf='hasPinnedRecords && isRowPinningToTop' class='igx-grid__tr--pinned igx-grid__tr--pinned-top'>
124-
<ng-container *ngTemplateOutlet="pinnedRecordsTemplate">
125-
</ng-container>
126-
</div>
131+
</div>
132+
</ng-container>
133+
</ng-template>
127134
<ng-template igxGridFor let-rowData [igxGridForOf]="data
128135
| gridTransaction:id:pipeTrigger
129136
| visibleColumns:hasVisibleColumns
@@ -148,10 +155,8 @@
148155
(onBeforeViewDetach)='viewDetachHandler($event)'>
149156
</ng-template>
150157
</ng-template>
151-
<div #pinContainer *ngIf='hasPinnedRecords && !isRowPinningToTop' class='igx-grid__tr--pinned igx-grid__tr--pinned-bottom' [style.bottom.px]='pinnedBottom'>
152-
<ng-container *ngTemplateOutlet="pinnedRecordsTemplate">
153-
</ng-container>
154-
</div>
158+
<ng-container *ngTemplateOutlet="hasPinnedRecords && !isRowPinningToTop ? pinnedRecordsTemplate : null">
159+
</ng-container>
155160
<ng-template #record_template let-rowIndex="index" let-rowData>
156161
<igx-grid-row [gridID]="id" [index]="rowIndex" [rowData]="rowData" #row>
157162
</igx-grid-row>

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ export class IgxGridFilteringPipe implements PipeTransform {
135135

136136
public transform(collection: any[], expressionsTree: IFilteringExpressionsTree,
137137
filterStrategy: IFilteringStrategy,
138-
advancedExpressionsTree: IFilteringExpressionsTree, id: string, pipeTrigger: number, filteringPipeTrigger: number) {
138+
advancedExpressionsTree: IFilteringExpressionsTree, id: string, pipeTrigger: number, filteringPipeTrigger: number, pinned?) {
139139
const grid = this.gridAPI.grid;
140140
const state = {
141141
expressionsTree: expressionsTree,
@@ -148,7 +148,7 @@ export class IgxGridFilteringPipe implements PipeTransform {
148148
}
149149

150150
const result = DataUtil.filter(cloneArray(collection), state);
151-
grid.filteredData = result;
151+
grid.setFilterData(result, pinned);
152152
return result;
153153
}
154154
}

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

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { SortingDirection } from '../../data-operations/sorting-expression.inter
1414
import { IgxGridTransaction } from '../tree-grid';
1515
import { IgxTransactionService } from '../../services';
1616
import { GridSummaryFunctions } from '../../test-utils/grid-functions.spec';
17+
import { IgxStringFilteringOperand } from '../../data-operations/filtering-condition';
1718

1819
describe('Row Pinning #grid', () => {
1920
const FIXED_ROW_CONTAINER = '.igx-grid__tr--pinned ';
@@ -227,7 +228,20 @@ describe('Row Pinning #grid', () => {
227228
expect(grid.getRowByIndex(1).rowID).toBe(fix.componentInstance.data[1]);
228229
});
229230

231+
it('should allow pinning onInit', () => {
232+
expect(() => {
233+
fix = TestBed.createComponent(GridRowPinningComponent);
234+
grid = fix.componentInstance.instance;
235+
grid.pinRow(fix.componentInstance.data[1]);
236+
fix.detectChanges();
237+
}).not.toThrow();
238+
expect(grid.pinnedRows.length).toBe(1);
239+
expect(grid.getRowByIndex(0).rowID).toBe(fix.componentInstance.data[1]);
240+
});
241+
230242
it('should pin rows when columns are grouped.', () => {
243+
grid.height = '550px';
244+
fix.detectChanges();
231245
// pin 1st and 2nd data row
232246
grid.pinRow(fix.componentInstance.data[0]);
233247
grid.pinRow(fix.componentInstance.data[1]);
@@ -259,6 +273,68 @@ describe('Row Pinning #grid', () => {
259273
expect(groupRows[0].groupRow.records[0].ID).toEqual('BLAUS');
260274
});
261275

276+
it('should apply filtering to both pinned and unpinned rows.', () => {
277+
grid.getRowByIndex(1).pin();
278+
fix.detectChanges();
279+
grid.getRowByIndex(5).pin();
280+
fix.detectChanges();
281+
282+
let pinRowContainer = fix.debugElement.queryAll(By.css(FIXED_ROW_CONTAINER));
283+
expect(pinRowContainer[0].children.length).toBe(2);
284+
expect(pinRowContainer[0].children[0].context.rowID).toBe(fix.componentInstance.data[1]);
285+
expect(pinRowContainer[0].children[1].context.rowID).toBe(fix.componentInstance.data[5]);
286+
287+
grid.filter('ID', 'B', IgxStringFilteringOperand.instance().condition('contains'), false);
288+
fix.detectChanges();
289+
290+
pinRowContainer = fix.debugElement.queryAll(By.css(FIXED_ROW_CONTAINER));
291+
expect(pinRowContainer[0].children.length).toBe(1);
292+
expect(pinRowContainer[0].children[0].context.rowID).toBe(fix.componentInstance.data[5]);
293+
});
294+
295+
it('should remove pinned container and recalculate sizes when all pinned records are filtered out.', () => {
296+
grid.getRowByIndex(1).pin();
297+
fix.detectChanges();
298+
let pinRowContainer = fix.debugElement.queryAll(By.css(FIXED_ROW_CONTAINER));
299+
expect(pinRowContainer.length).toBe(1);
300+
301+
let expectedHeight = parseInt(grid.height, 10) - grid.pinnedRowHeight - 18 - grid.theadRow.nativeElement.offsetHeight;
302+
expect(grid.calcHeight - expectedHeight).toBeLessThanOrEqual(1);
303+
304+
grid.filter('ID', 'B', IgxStringFilteringOperand.instance().condition('startsWith'), false);
305+
fix.detectChanges();
306+
307+
pinRowContainer = fix.debugElement.queryAll(By.css(FIXED_ROW_CONTAINER));
308+
expect(pinRowContainer.length).toBe(0);
309+
310+
expect(grid.pinnedRowHeight).toBe(0);
311+
expectedHeight = parseInt(grid.height, 10) - grid.pinnedRowHeight - 18 - grid.theadRow.nativeElement.offsetHeight;
312+
expect(grid.calcHeight - expectedHeight).toBeLessThanOrEqual(1);
313+
});
314+
315+
it('should return correct filterData collection.', () => {
316+
grid.getRowByIndex(1).pin();
317+
fix.detectChanges();
318+
grid.getRowByIndex(5).pin();
319+
fix.detectChanges();
320+
321+
grid.filter('ID', 'B', IgxStringFilteringOperand.instance().condition('contains'), false);
322+
fix.detectChanges();
323+
324+
let gridFilterData = grid.filteredData;
325+
expect(gridFilterData.length).toBe(7);
326+
expect(gridFilterData[0].ID).toBe('BLAUS');
327+
expect(gridFilterData[1].ID).toBe('BERGS');
328+
329+
fix.componentInstance.pinningConfig = { columns: ColumnPinningPosition.Start, rows: RowPinningPosition.Bottom };
330+
fix.detectChanges();
331+
332+
gridFilterData = grid.filteredData;
333+
expect(gridFilterData.length).toBe(7);
334+
expect(gridFilterData[0].ID).toBe('BLAUS');
335+
expect(gridFilterData[1].ID).toBe('BERGS');
336+
});
337+
262338
it('should apply sorting to both pinned and unpinned rows.', () => {
263339
grid.getRowByIndex(1).pin();
264340
grid.getRowByIndex(5).pin();
@@ -540,6 +616,7 @@ describe('Row Pinning #grid', () => {
540616
@Component({
541617
template: `
542618
<igx-grid
619+
[allowFiltering]='true'
543620
[pinning]='pinningConfig'
544621
[width]='"800px"'
545622
[height]='"500px"'

0 commit comments

Comments
 (0)