Skip to content

Commit 5efbf5d

Browse files
committed
Merge remote-tracking branch 'origin/master' into mkirova/row-pinning-export-to-excel
2 parents b62e151 + 8af41c0 commit 5efbf5d

File tree

9 files changed

+202
-33
lines changed

9 files changed

+202
-33
lines changed

Diff for: projects/igniteui-angular/src/lib/core/styles/components/navbar/_navbar-theme.scss

+1
Original file line numberDiff line numberDiff line change
@@ -155,5 +155,6 @@
155155

156156
%igx-navbar-title {
157157
@include igx-type-style($type-scale, $title);
158+
margin-bottom: 0;
158159
}
159160
}

Diff for: projects/igniteui-angular/src/lib/grids/filtering/base/grid-filtering-row.component.ts

+7-5
Original file line numberDiff line numberDiff line change
@@ -462,12 +462,14 @@ export class IgxGridFilteringRowComponent implements AfterViewInit {
462462
this.expressionsList[0].expression.searchVal === null &&
463463
this.expressionsList[0].expression.condition.isUnary === false) {
464464
this.filteringService.getExpressions(this.column.field).pop();
465+
466+
this.filter();
465467
} else {
466-
this.expressionsList.forEach((item) => {
467-
if (item.expression.searchVal === null && !item.expression.condition.isUnary) {
468-
this.filteringService.removeExpression(this.column.field, this.expressionsList.indexOf(item));
469-
}
470-
});
468+
const condToRemove = this.expressionsList.filter(ex => ex.expression.searchVal === null && !ex.expression.condition.isUnary);
469+
if (condToRemove && condToRemove.length > 0) {
470+
condToRemove.forEach(c => this.filteringService.removeExpression(this.column.field, this.expressionsList.indexOf(c)));
471+
this.filter();
472+
}
471473
}
472474

473475
this.filteringService.isFilterRowVisible = false;

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

+17
Original file line numberDiff line numberDiff line change
@@ -1969,6 +1969,23 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => {
19691969
const activeFilterIcon = header.nativeElement.querySelector('.igx-excel-filter__icon--filtered');
19701970
expect(activeFilterIcon).toBeDefined('no active filter icon was found');
19711971
}));
1972+
1973+
it('Should clear non-unary conditions with null searchVal when close', fakeAsync(() => {
1974+
GridFunctions.clickFilterCellChip(fix, 'ProductName');
1975+
fix.detectChanges();
1976+
1977+
GridFunctions.openFilterDD(fix.debugElement);
1978+
const dropdownList = fix.debugElement.query(By.css('div.igx-drop-down__list.igx-toggle'));
1979+
GridFunctions.selectFilteringCondition('Empty', dropdownList);
1980+
fix.detectChanges();
1981+
GridFunctions.openFilterDD(fix.debugElement);
1982+
GridFunctions.selectFilteringCondition('Contains', dropdownList);
1983+
fix.detectChanges();
1984+
GridFunctions.closeFilterRow(fix);
1985+
1986+
const headerChip = GridFunctions.getFilterChipsForColumn('ProductName', fix);
1987+
expect(headerChip.length).toBe(1);
1988+
}));
19721989
});
19731990

19741991
describe('Integration scenarios', () => {

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

+44
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,50 @@ describe('Row Pinning #grid', () => {
699699
verifyDOMMatchesLayoutSettings(gridUnpinnedRow, fix.componentInstance.colGroups);
700700
});
701701
});
702+
describe(' Hiding', () => {
703+
beforeEach(fakeAsync(() => {
704+
fix = TestBed.createComponent(GridRowPinningComponent);
705+
fix.detectChanges();
706+
grid = fix.componentInstance.instance;
707+
tick();
708+
fix.detectChanges();
709+
}));
710+
711+
it('should hide columns in pinned and unpinned area', () => {
712+
// pin 2nd data row
713+
grid.pinRow(fix.componentInstance.data[1]);
714+
fix.detectChanges();
715+
const hiddenCol = grid.columns[1];
716+
hiddenCol.hidden = true;
717+
fix.detectChanges();
718+
719+
const pinnedCells = grid.pinnedRows[0].cells;
720+
expect(pinnedCells.filter(cell => cell.column.field === hiddenCol.field).length).toBe(0);
721+
722+
const unpinnedCells = grid.rowList.first.cells;
723+
expect(unpinnedCells.filter(cell => cell.column.field === hiddenCol.field).length).toBe(0);
724+
725+
expect(pinnedCells.length).toBe(unpinnedCells.length);
726+
727+
const headerCells = grid.headerCellList;
728+
expect(headerCells.filter(cell => cell.column.field === hiddenCol.field).length).toBe(0);
729+
730+
expect(grid.pinnedRows.length).toBe(1);
731+
const pinRowContainer = fix.debugElement.queryAll(By.css(FIXED_ROW_CONTAINER));
732+
expect(pinRowContainer.length).toBe(1);
733+
expect(pinRowContainer[0].children.length).toBe(1);
734+
expect(pinRowContainer[0].children[0].context.rowID).toBe(fix.componentInstance.data[1]);
735+
expect(pinRowContainer[0].children[0].nativeElement).toBe(grid.getRowByIndex(0).nativeElement);
736+
737+
expect(grid.getRowByIndex(1).rowID).toBe(fix.componentInstance.data[0]);
738+
expect(grid.getRowByIndex(2).rowID).toBe(fix.componentInstance.data[2]);
739+
740+
// 1 records pinned + 2px border
741+
expect(grid.pinnedRowHeight).toBe(grid.renderedRowHeight + 2);
742+
const expectedHeight = parseInt(grid.height, 10) - grid.pinnedRowHeight - 18 - grid.theadRow.nativeElement.offsetHeight;
743+
expect(grid.calcHeight - expectedHeight).toBeLessThanOrEqual(1);
744+
});
745+
});
702746
});
703747

704748
@Component({

Diff for: projects/igniteui-angular/src/lib/grids/state.directive.spec.ts

+25-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ describe('IgxGridState - input properties #grid', () => {
7272

7373
it('getState should return corect JSON string', () => {
7474
// tslint:disable-next-line:max-line-length
75-
const initialGridState = '{"columns":[{"pinned":true,"sortable":true,"filterable":true,"editable":false,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"testCss","headerGroupClasses":"","maxWidth":"300px","groupable":false,"movable":true,"hidden":false,"dataType":"number","hasSummary":false,"field":"ProductID","width":"150px","header":"Product ID","resizable":true,"searchable":false},{"pinned":false,"sortable":true,"filterable":true,"editable":false,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,"movable":true,"hidden":false,"dataType":"string","hasSummary":false,"field":"ProductName","width":"150px","header":"Prodyct Name","resizable":true,"searchable":true},{"pinned":false,"sortable":false,"filterable":true,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":false,"movable":false,"hidden":false,"dataType":"boolean","hasSummary":true,"field":"InStock","width":"140px","header":"In Stock","resizable":true,"searchable":true},{"pinned":false,"sortable":true,"filterable":false,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,"movable":false,"hidden":false,"dataType":"date","hasSummary":false,"field":"OrderDate","width":"110px","header":"Date ordered","resizable":false,"searchable":true}],"filtering":{"filteringOperands":[],"operator":0},"sorting":[],"groupBy":{"expressions":[],"expansion":[],"defaultExpanded":true},"paging":{"index":0,"recordsPerPage":15,"metadata":{"countPages":1,"countRecords":10,"error":0}},"cellSelection":[],"rowSelection":[],"columnSelection":[]}';
75+
const initialGridState = '{"columns":[{"pinned":true,"sortable":true,"filterable":true,"editable":false,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"testCss","headerGroupClasses":"","maxWidth":"300px","groupable":false,"movable":true,"hidden":false,"dataType":"number","hasSummary":false,"field":"ProductID","width":"150px","header":"Product ID","resizable":true,"searchable":false},{"pinned":false,"sortable":true,"filterable":true,"editable":false,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,"movable":true,"hidden":false,"dataType":"string","hasSummary":false,"field":"ProductName","width":"150px","header":"Prodyct Name","resizable":true,"searchable":true},{"pinned":false,"sortable":false,"filterable":true,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":false,"movable":false,"hidden":false,"dataType":"boolean","hasSummary":true,"field":"InStock","width":"140px","header":"In Stock","resizable":true,"searchable":true},{"pinned":false,"sortable":true,"filterable":false,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,"movable":false,"hidden":false,"dataType":"date","hasSummary":false,"field":"OrderDate","width":"110px","header":"Date ordered","resizable":false,"searchable":true}],"filtering":{"filteringOperands":[],"operator":0},"sorting":[],"groupBy":{"expressions":[],"expansion":[],"defaultExpanded":true},"paging":{"index":0,"recordsPerPage":15,"metadata":{"countPages":1,"countRecords":10,"error":0}},"cellSelection":[],"rowSelection":[],"columnSelection":[],"rowPinning":[]}';
7676
const fix = TestBed.createComponent(IgxGridStateComponent);
7777
fix.detectChanges();
7878

@@ -392,6 +392,30 @@ describe('IgxGridState - input properties #grid', () => {
392392
expect(gridState).toBe(rowSelectionState);
393393
});
394394

395+
it('setState should correctly restore grid row pinning state from object', () => {
396+
const fix = TestBed.createComponent(IgxGridStateComponent);
397+
fix.detectChanges();
398+
const grid = fix.componentInstance.grid;
399+
grid.primaryKey = 'ProductID';
400+
fix.detectChanges();
401+
const state = fix.componentInstance.state;
402+
const rowPinState = '{"rowPinning":[1,3]}';
403+
const initialState = '{"rowPinning":[]}';
404+
const rowPinStateObject = JSON.parse(rowPinState);
405+
406+
let gridState = state.getState(true, 'rowPinning');
407+
expect(gridState).toBe(initialState);
408+
409+
state.setState(rowPinStateObject);
410+
fix.detectChanges();
411+
412+
expect(grid.pinnedRows.length).toBe(2);
413+
expect(grid.pinnedRows[0].rowID).toBe(1);
414+
expect(grid.pinnedRows[1].rowID).toBe(3);
415+
gridState = state.getState(true, 'rowPinning');
416+
expect(gridState).toBe(rowPinState);
417+
});
418+
395419
it('setState should correctly restore grid cell selection state from string', () => {
396420
const fix = TestBed.createComponent(IgxGridStateComponent);
397421
fix.detectChanges();

Diff for: projects/igniteui-angular/src/lib/grids/state.directive.ts

+42-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { GridSelectionRange } from './selection/selection.service';
1212
import { IGroupByExpandState } from '../data-operations/groupby-expand-state.interface';
1313
import { IGroupingState } from '../data-operations/groupby-state.interface';
1414
import { IgxGridComponent } from './grid/grid.component';
15+
import { IPinningConfig } from './common/grid.interface';
1516

1617
export interface IGridState {
1718
columns?: IColumnState[];
@@ -23,6 +24,8 @@ export interface IGridState {
2324
cellSelection?: GridSelectionRange[];
2425
rowSelection?: any[];
2526
columnSelection?: string[];
27+
rowPinning?: any[];
28+
pinningConfig?: IPinningConfig;
2629
}
2730

2831
export interface IGridStateOptions {
@@ -35,6 +38,8 @@ export interface IGridStateOptions {
3538
cellSelection?: boolean;
3639
rowSelection?: boolean;
3740
columnSelection?: boolean;
41+
rowPinning?: boolean;
42+
pinningConfig?: boolean;
3843
}
3944

4045
export interface IColumnState {
@@ -66,6 +71,8 @@ const SORTING = 'sorting';
6671
const GROUPBY = 'groupBy';
6772
const PAGING = 'paging';
6873
const ROW_SELECTION = 'rowSelection';
74+
const ROW_PINNING = 'rowPinning';
75+
const PINNING_CONFIG = 'pinningConfig';
6976
const CELL_SELECTION = 'cellSelection';
7077
const COLUMN_SELECTION = 'columnSelection';
7178

@@ -83,7 +90,8 @@ export class IgxGridStateDirective {
8390
paging: true,
8491
cellSelection: true,
8592
rowSelection: true,
86-
columnSelection: true
93+
columnSelection: true,
94+
rowPinning: true
8795
};
8896

8997
private state: IGridState;
@@ -216,6 +224,14 @@ export class IgxGridStateDirective {
216224
this.restoreRowSelection(state as any[]);
217225
break;
218226
}
227+
case ROW_PINNING: {
228+
this.restoreRowPinning(state as any[]);
229+
break;
230+
}
231+
case PINNING_CONFIG: {
232+
this.restorePinningConfig(state as IPinningConfig);
233+
break;
234+
}
219235
case CELL_SELECTION: {
220236
this.restoreCellSelection(state as GridSelectionRange[]);
221237
break;
@@ -279,6 +295,14 @@ export class IgxGridStateDirective {
279295
Object.assign(state, this.getRowSelection());
280296
break;
281297
}
298+
case ROW_PINNING: {
299+
Object.assign(state, this.getRowPinning());
300+
break;
301+
}
302+
case PINNING_CONFIG: {
303+
Object.assign(state, this.getPinningConfig());
304+
break;
305+
}
282306
case CELL_SELECTION: {
283307
Object.assign(state, this.getCellSelection());
284308
break;
@@ -360,6 +384,15 @@ export class IgxGridStateDirective {
360384
return { rowSelection: selection };
361385
}
362386

387+
private getRowPinning(): IGridState {
388+
const pinned = this.grid.pinnedRows.map(x => x.rowID);
389+
return { rowPinning: pinned };
390+
}
391+
392+
private getPinningConfig(): IGridState {
393+
return { pinningConfig: this.grid.pinning };
394+
}
395+
363396
private getColumnSelection(): IGridState {
364397
const selection = this.grid.selectedColumns().map(c => c.field);
365398
return { columnSelection: selection };
@@ -444,6 +477,14 @@ export class IgxGridStateDirective {
444477
this.grid.selectRows(state);
445478
}
446479

480+
private restoreRowPinning(state: any[]) {
481+
state.forEach(rowID => this.grid.pinRow(rowID));
482+
}
483+
484+
private restorePinningConfig(state: IPinningConfig) {
485+
this.grid.pinning = state;
486+
}
487+
447488
private restoreColumnSelection(state: string[]) {
448489
this.grid.selectColumns(state);
449490
}

Diff for: src/app/grid-column-pinning/grid-column-pinning.sample.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export class GridColumnPinningSampleComponent implements OnInit {
103103

104104
togglePinRow(index) {
105105
const rec = this.data[index];
106-
this.grid1.isRecordPinned(rec) ?
106+
!this.grid1.isRecordPinned(rec) ?
107107
this.grid1.pinRow(rec) :
108108
this.grid1.unpinRow(rec)
109109
}

Diff for: src/app/grid-row-pinning/grid-row-pinning.sample.html

+25-18
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,34 @@
66
<button (click)="exportButtonHandler()">Export</button>
77
<div class="sample-content">
88
<div class="sample-column">
9+
<div class="sample-buttons">
10+
<button igxButton="raised" (click)="saveGridState()">Save state</button>
11+
<button igxButton="raised" (click)="restoreGridState()">Restore state</button>
12+
</div>
913
<div class="sample-switches">
1014
<igx-switch (change)='onRowChange()' style="padding-left: 10px"> Bottom Row Pinning toggle</igx-switch>
1115
<igx-switch (change)='onChange()' style="padding-left: 10px"> Right Column Pinning toggle</igx-switch>
1216
</div>
13-
<igx-grid [allowFiltering]='true' [primaryKey]='"ID"' [pinning]="pinningConfig" [showToolbar]='true' [columnPinning]='true' #grid1 [data]="data" [width]="'800px'" [height]="'500px'" [rowSelectable]="false">
14-
<igx-column width='70px' [filterable]='false'>
15-
<ng-template igxCell let-cell="cell" let-val>
16-
<igx-icon class="pin-icon" (mousedown)="togglePining(cell.row, $event)">
17-
{{cell.row.pinned ? 'lock' : 'lock_open'}}
18-
</igx-icon>
19-
</ng-template>
20-
</igx-column>
21-
<igx-column width='100px' [filterable]='false'>
22-
<ng-template igxCell let-cell="cell" let-val>
23-
<button (click)="grid1.deleteRow(cell.row.rowID)">Delete</button>
24-
</ng-template>
25-
</igx-column>
26-
<igx-column *ngFor="let c of columns" [sortable]="true" [field]="c.field" [header]="c.field" [width]="c.width" [pinned]='c.pinned' [groupable]='c.groupable'
27-
[hidden]='c.hidden' [editable]='true'>
28-
</igx-column>
29-
</igx-grid>
17+
<igx-grid [igxGridState]="options" [allowFiltering]='true' [primaryKey]='"ID"' [pinning]="pinningConfig"
18+
[columnHiding]='true' [showToolbar]='true' [columnPinning]='true' #grid1 [data]="data" [width]="'800px'"
19+
[height]="'500px'" [rowSelectable]="false">
20+
<igx-column width='70px' [filterable]='false'>
21+
<ng-template igxCell let-cell="cell" let-val>
22+
<igx-icon class="pin-icon" (mousedown)="togglePining(cell.row, $event)">
23+
{{cell.row.pinned ? 'lock' : 'lock_open'}}
24+
</igx-icon>
25+
</ng-template>
26+
</igx-column>
27+
<igx-column width='100px' [filterable]='false'>
28+
<ng-template igxCell let-cell="cell" let-val>
29+
<button (click)="grid1.deleteRow(cell.row.rowID)">Delete</button>
30+
</ng-template>
31+
</igx-column>
32+
<igx-column *ngFor="let c of columns" [sortable]="true" [field]="c.field" [header]="c.field"
33+
[width]="c.width" [pinned]='c.pinned' [groupable]='c.groupable' [hidden]='c.hidden'
34+
[editable]='true'>
35+
</igx-column>
36+
</igx-grid>
3037
</div>
3138
</div>
32-
</div>
39+
</div>

0 commit comments

Comments
 (0)