diff --git a/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts b/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts index d0d19f1597c..f362baa37f2 100644 --- a/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts +++ b/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts @@ -2479,15 +2479,7 @@ export class IgxGridBaseDirective extends DisplayDensityBase implements */ protected _columnPinning = false; - - /** - * @hidden - */ - public get pinnedRecords() { - return this._pinnedRecords; - } - - protected _pinnedRecords = []; + protected _pinnedRecordIDs = []; /** * @hidden @@ -2652,6 +2644,32 @@ export class IgxGridBaseDirective extends DisplayDensityBase implements }); } + /** + * @hidden + * @internal + */ + public isRecordPinned(rec) { + const id = this.primaryKey ? rec[this.primaryKey] : rec; + return this._pinnedRecordIDs.indexOf(id) !== -1; + } + + /** + * @hidden + * @internal + */ + public pinRecordIndex(rec) { + const id = this.primaryKey ? rec[this.primaryKey] : rec; + return this._pinnedRecordIDs.indexOf(id); + } + + /** + * @hidden + * @internal + */ + public get hasPinnedRecords() { + return this._pinnedRecordIDs.length > 0; + } + private keydownHandler = (event) => { const key = event.key.toLowerCase(); if ((isNavigationKey(key) && event.keyCode !== 32) || key === 'tab' || key === 'pagedown' || key === 'pageup') { @@ -4066,8 +4084,7 @@ export class IgxGridBaseDirective extends DisplayDensityBase implements * @param index The index at which to insert the row in the pinned collection. */ public pinRow(rowID: any, index?: number): boolean { - const rec = this.gridAPI.get_rec_by_id(rowID); - if (!rec || this.pinnedRecords.indexOf(rec) !== -1 || this.data.indexOf(rec) === -1) { + if (this._pinnedRecordIDs.indexOf(rowID) !== -1) { return false; } const row = this.gridAPI.get_row_by_key(rowID); @@ -4080,7 +4097,9 @@ export class IgxGridBaseDirective extends DisplayDensityBase implements }; this.onRowPinning.emit(eventArgs); - this.pinnedRecords.splice(eventArgs.insertAtIndex || this.pinnedRecords.length, 0, rec); + this.endEdit(true); + + this._pinnedRecordIDs.splice(eventArgs.insertAtIndex || this._pinnedRecordIDs.length, 0, rowID); this._pipeTrigger++; if (this.gridAPI.grid) { this.notifyChanges(true); @@ -4098,9 +4117,8 @@ export class IgxGridBaseDirective extends DisplayDensityBase implements * @param rowID The row id - primaryKey value or the data record instance. */ public unpinRow(rowID: any) { - const rec = this.gridAPI.get_rec_by_id(rowID); - const index = this.pinnedRecords.indexOf(rec); - if (index === -1 || !rec) { + const index = this._pinnedRecordIDs.indexOf(rowID); + if (index === -1) { return false; } const row = this.gridAPI.get_row_by_key(rowID); @@ -4110,7 +4128,8 @@ export class IgxGridBaseDirective extends DisplayDensityBase implements row: row }; this.onRowPinning.emit(eventArgs); - this.pinnedRecords.splice(index, 1); + this.endEdit(true); + this._pinnedRecordIDs.splice(index, 1); this._pipeTrigger++; if (this.gridAPI.grid) { this.cdr.detectChanges(); @@ -4121,7 +4140,7 @@ export class IgxGridBaseDirective extends DisplayDensityBase implements get pinnedRowHeight() { const containerHeight = this.pinContainer ? this.pinContainer.nativeElement.offsetHeight : 0; - return this.pinnedRecords.length > 0 ? containerHeight : 0; + return this._pinnedRecordIDs.length > 0 ? containerHeight : 0; } get totalHeight() { diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid.component.html b/projects/igniteui-angular/src/lib/grids/grid/grid.component.html index a861373f3cb..7f09c419813 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid.component.html +++ b/projects/igniteui-angular/src/lib/grids/grid/grid.component.html @@ -109,8 +109,10 @@ [igxColumnMovingDrop]="headerContainer" [attr.droppable]="true" id="left" class="igx-grid__scroll-on-drag-pinned" [style.left.px]="pinnedWidth"> - @@ -118,14 +120,14 @@ -
+
diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid.component.ts b/projects/igniteui-angular/src/lib/grids/grid/grid.component.ts index 5a3ff120323..01a11554e54 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid.component.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid.component.ts @@ -830,7 +830,7 @@ export class IgxGridComponent extends IgxGridBaseDirective implements GridType, if (pinned && !this.isRowPinningToTop) { rowIndex = rowIndex + this.dataView.length; } - rowIndex = !pinned && this.isRowPinningToTop ? rowIndex + this.pinnedRecords.length : rowIndex; + rowIndex = !pinned && this.isRowPinningToTop ? rowIndex + this._pinnedRecordIDs.length : rowIndex; if (this.isDetailRecord(rowData)) { const cachedData = this.childDetailTemplates.get(rowData.detailsData); const rowID = this.primaryKey ? rowData.detailsData[this.primaryKey] : this.data.indexOf(rowData.detailsData); diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid.pipes.ts b/projects/igniteui-angular/src/lib/grids/grid/grid.pipes.ts index acf30127d09..773d244101f 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid.pipes.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid.pipes.ts @@ -164,16 +164,20 @@ export class IgxGridRowPinningPipe implements PipeTransform { constructor(private gridAPI: GridBaseAPIService) {} - public transform(collection: any[] , id: string, pipeTrigger: number) { + public transform(collection: any[] , id: string, isPinned = false, pipeTrigger: number) { const grid = this.gridAPI.grid; - const pinnedRows = grid.pinnedRecords; - if (pinnedRows.length === 0) { - return collection; + + if (!grid.hasPinnedRecords) { + return isPinned ? [] : collection; } const result = collection.filter((value, index) => { - return pinnedRows.indexOf(value) === -1; + return isPinned ? grid.isRecordPinned(value) : !grid.isRecordPinned(value); }); + if (isPinned) { + // pinned records should be ordered as they were pinned. + result.sort((rec1, rec2) => grid.pinRecordIndex(rec1) - grid.pinRecordIndex(rec2)); + } return result; } } diff --git a/projects/igniteui-angular/src/lib/grids/grid/row-pinning.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/row-pinning.spec.ts index 5177c0ff894..e87f38faba7 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/row-pinning.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/row-pinning.spec.ts @@ -8,9 +8,12 @@ import { configureTestSuite } from '../../test-utils/configure-suite'; import { ColumnPinningPosition, RowPinningPosition } from '../common/enums'; import { IPinningConfig } from '../common/grid.interface'; import { SampleTestData } from '../../test-utils/sample-test-data.spec'; +import { IgxGridTransaction } from '../tree-grid'; +import { IgxTransactionService } from '../../services'; describe('Row Pinning #grid', () => { const FIXED_ROW_CONTAINER = '.igx-grid__tr--pinned '; + const CELL_CSS_CLASS = '.igx-grid__td'; configureTestSuite(); let fix; let grid: IgxGridComponent; @@ -18,7 +21,8 @@ describe('Row Pinning #grid', () => { beforeAll(async(() => { TestBed.configureTestingModule({ declarations: [ - GridRowPinningComponent + GridRowPinningComponent, + GridRowPinningWithTransactionsComponent ], imports: [ NoopAnimationsModule, @@ -42,7 +46,7 @@ describe('Row Pinning #grid', () => { grid.pinRow(fix.componentInstance.data[1]); fix.detectChanges(); - expect(grid.pinnedRecords.length).toBe(1); + expect(grid.pinnedRows.length).toBe(1); let pinRowContainer = fix.debugElement.queryAll(By.css(FIXED_ROW_CONTAINER)); expect(pinRowContainer.length).toBe(1); expect(pinRowContainer[0].children.length).toBe(1); @@ -78,7 +82,7 @@ describe('Row Pinning #grid', () => { grid.pinRow(fix.componentInstance.data[1]); fix.detectChanges(); - expect(grid.pinnedRecords.length).toBe(1); + expect(grid.pinnedRows.length).toBe(1); let pinRowContainer = fix.debugElement.queryAll(By.css(FIXED_ROW_CONTAINER)); expect(pinRowContainer.length).toBe(1); expect(pinRowContainer[0].children.length).toBe(1); @@ -138,7 +142,7 @@ describe('Row Pinning #grid', () => { grid.pinRow(fix.componentInstance.data[1]); fix.detectChanges(); - expect(grid.pinnedRecords.length).toBe(1); + expect(grid.pinnedRows.length).toBe(1); let pinRowContainer = fix.debugElement.queryAll(By.css(FIXED_ROW_CONTAINER)); expect(pinRowContainer.length).toBe(1); expect(pinRowContainer[0].children.length).toBe(1); @@ -153,7 +157,7 @@ describe('Row Pinning #grid', () => { grid.unpinRow(fix.componentInstance.data[1]); fix.detectChanges(); - expect(grid.pinnedRecords.length).toBe(0); + expect(grid.pinnedRows.length).toBe(0); pinRowContainer = fix.debugElement.queryAll(By.css(FIXED_ROW_CONTAINER)); expect(pinRowContainer.length).toBe(0); @@ -167,7 +171,7 @@ describe('Row Pinning #grid', () => { row.pin(); fix.detectChanges(); - expect(grid.pinnedRecords.length).toBe(1); + expect(grid.pinnedRows.length).toBe(1); let pinRowContainer = fix.debugElement.queryAll(By.css(FIXED_ROW_CONTAINER)); expect(pinRowContainer.length).toBe(1); expect(pinRowContainer[0].children.length).toBe(1); @@ -181,7 +185,7 @@ describe('Row Pinning #grid', () => { row.unpin(); fix.detectChanges(); - expect(grid.pinnedRecords.length).toBe(0); + expect(grid.pinnedRows.length).toBe(0); pinRowContainer = fix.debugElement.queryAll(By.css(FIXED_ROW_CONTAINER)); expect(pinRowContainer.length).toBe(0); @@ -195,7 +199,7 @@ describe('Row Pinning #grid', () => { row.pinned = true; fix.detectChanges(); - expect(grid.pinnedRecords.length).toBe(1); + expect(grid.pinnedRows.length).toBe(1); let pinRowContainer = fix.debugElement.queryAll(By.css(FIXED_ROW_CONTAINER)); expect(pinRowContainer.length).toBe(1); expect(pinRowContainer[0].children.length).toBe(1); @@ -209,7 +213,7 @@ describe('Row Pinning #grid', () => { row.pinned = false; fix.detectChanges(); - expect(grid.pinnedRecords.length).toBe(0); + expect(grid.pinnedRows.length).toBe(0); pinRowContainer = fix.debugElement.queryAll(By.css(FIXED_ROW_CONTAINER)); expect(pinRowContainer.length).toBe(0); @@ -217,6 +221,85 @@ describe('Row Pinning #grid', () => { expect(grid.getRowByIndex(1).rowID).toBe(fix.componentInstance.data[1]); }); }); + + describe(' Editing ', () => { + beforeEach(fakeAsync(() => { + fix = TestBed.createComponent(GridRowPinningWithTransactionsComponent); + fix.detectChanges(); + grid = fix.componentInstance.instance; + tick(); + fix.detectChanges(); + })); + + it('should allow pinning edited row.', () => { + grid.updateCell('New value', 'ANTON', 'CompanyName'); + fix.detectChanges(); + grid.pinRow('ANTON'); + fix.detectChanges(); + + expect(grid.pinnedRows.length).toBe(1); + const pinRowContainer = fix.debugElement.queryAll(By.css(FIXED_ROW_CONTAINER)); + expect(pinRowContainer.length).toBe(1); + expect(pinRowContainer[0].children.length).toBe(1); + expect(pinRowContainer[0].children[0].context.rowID).toBe('ANTON'); + expect(pinRowContainer[0].children[0].context.rowData.CompanyName).toBe('New value'); + }); + + it('should allow pinning deleted row.', () => { + grid.deleteRow('ALFKI'); + fix.detectChanges(); + grid.pinRow('ALFKI'); + fix.detectChanges(); + + expect(grid.pinnedRows.length).toBe(1); + const pinRowContainer = fix.debugElement.queryAll(By.css(FIXED_ROW_CONTAINER)); + expect(pinRowContainer.length).toBe(1); + expect(pinRowContainer[0].children.length).toBe(1); + expect(pinRowContainer[0].children[0].context.rowID).toBe('ALFKI'); + }); + + it('should allow pinning added row.', () => { + + grid.addRow({ 'ID': 'Test', 'CompanyName': 'Test'}); + fix.detectChanges(); + + grid.pinRow('Test'); + fix.detectChanges(); + expect(grid.pinnedRows.length).toBe(1); + const pinRowContainer = fix.debugElement.queryAll(By.css(FIXED_ROW_CONTAINER)); + expect(pinRowContainer.length).toBe(1); + expect(pinRowContainer[0].children.length).toBe(1); + expect(pinRowContainer[0].children[0].context.rowID).toBe('Test'); + }); + + it('should stop editing when edited row is pinned/unpinned.', () => { + grid.getColumnByName('CompanyName').editable = true; + fix.detectChanges(); + let cell = grid.getCellByColumn(0, 'CompanyName'); + let cellDomNumber = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS))[1]; + cellDomNumber.triggerEventHandler('dblclick', {}); + fix.detectChanges(); + + expect(cell.editMode).toBeTruthy(); + + grid.pinRow(cell.row.rowID); + fix.detectChanges(); + + cell = grid.getCellByColumn(0, 'CompanyName'); + expect(cell.editMode).toBeFalsy(); + + cellDomNumber = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS))[1]; + cellDomNumber.triggerEventHandler('dblclick', {}); + fix.detectChanges(); + + expect(cell.editMode).toBeTruthy(); + grid.unpinRow(cell.row.rowID); + fix.detectChanges(); + cell = grid.getCellByColumn(0, 'CompanyName'); + expect(cell.editMode).toBeFalsy(); + }); + + }); }); @Component({ @@ -237,3 +320,21 @@ export class GridRowPinningComponent { @ViewChild(IgxGridComponent, { read: IgxGridComponent, static: true }) public instance: IgxGridComponent; } + + +@Component({ + template: ` + + + `, + providers: [{ provide: IgxGridTransaction, useClass: IgxTransactionService }] +}) +export class GridRowPinningWithTransactionsComponent extends GridRowPinningComponent { + public data = SampleTestData.contactInfoDataFull(); +} diff --git a/projects/igniteui-angular/src/lib/grids/row.directive.ts b/projects/igniteui-angular/src/lib/grids/row.directive.ts index ad1798a2453..6708713f30b 100644 --- a/projects/igniteui-angular/src/lib/grids/row.directive.ts +++ b/projects/igniteui-angular/src/lib/grids/row.directive.ts @@ -65,7 +65,7 @@ export class IgxRowDirective implemen * ``` */ public get pinned(): boolean { - return this.grid.pinnedRecords.indexOf(this.rowData) !== -1; + return this.grid.isRecordPinned(this.rowData); } /** * Sets whether the row is pinned. diff --git a/src/app/grid-column-pinning/grid-column-pinning.sample.ts b/src/app/grid-column-pinning/grid-column-pinning.sample.ts index 5d4971c6148..d69dcdcc271 100644 --- a/src/app/grid-column-pinning/grid-column-pinning.sample.ts +++ b/src/app/grid-column-pinning/grid-column-pinning.sample.ts @@ -103,9 +103,9 @@ export class GridColumnPinningSampleComponent implements OnInit { togglePinRow(index) { const rec = this.data[index]; - this.grid1.pinnedRecords.indexOf(rec) === -1 ? - this.grid1.pinRow(this.data[index]) : - this.grid1.unpinRow(this.data[index]) + this.grid1.isRecordPinned(rec) ? + this.grid1.pinRow(rec) : + this.grid1.unpinRow(rec) } } diff --git a/src/app/grid-row-pinning/grid-row-pinning.sample.html b/src/app/grid-row-pinning/grid-row-pinning.sample.html index cbd2f4bf0f1..184cd8fa447 100644 --- a/src/app/grid-row-pinning/grid-row-pinning.sample.html +++ b/src/app/grid-row-pinning/grid-row-pinning.sample.html @@ -2,6 +2,7 @@ Allows rows to be pinned to the beginning/end of the grid. +
@@ -16,8 +17,13 @@ + + + + + + [hidden]='c.hidden' [editable]='true'>
diff --git a/src/app/grid-row-pinning/grid-row-pinning.sample.ts b/src/app/grid-row-pinning/grid-row-pinning.sample.ts index b486e6e27c0..24c7b90300d 100644 --- a/src/app/grid-row-pinning/grid-row-pinning.sample.ts +++ b/src/app/grid-row-pinning/grid-row-pinning.sample.ts @@ -1,9 +1,9 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { IgxGridComponent, ColumnPinningPosition, RowPinningPosition, IgxGridRowComponent } from 'igniteui-angular'; +import { IgxGridComponent, ColumnPinningPosition, RowPinningPosition, IgxGridRowComponent, IgxTransactionService, IgxGridTransaction } from 'igniteui-angular'; import { IPinningConfig } from 'projects/igniteui-angular/src/lib/grids/common/grid.interface'; @Component({ - providers: [], + providers: [{ provide: IgxGridTransaction, useClass: IgxTransactionService }], selector: 'app-grid-row-pinning-sample', styleUrls: ['grid-row-pinning.sample.css'], templateUrl: 'grid-row-pinning.sample.html' @@ -83,7 +83,7 @@ export class GridRowPinningSampleComponent implements OnInit { togglePinRow(index) { const rec = this.data[index]; - this.grid1.pinnedRecords.indexOf(rec) === -1 ? + this.grid1.isRecordPinned(rec)? this.grid1.pinRow(this.data[index]) : this.grid1.unpinRow(this.data[index]) }