diff --git a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.spec.ts b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.spec.ts index 954eae23183..89fe3bc20f8 100644 --- a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.spec.ts +++ b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.spec.ts @@ -197,6 +197,44 @@ describe('igxGridEditingActions #grid ', () => { expect(pinningIcons.length).toBe(1); expect(pinningIcons[0].nativeElement.className.indexOf('igx-button--disabled') === -1).toBeTruthy(); }); + + it('should emit correct rowPinning arguments with pinning actions', () => { + spyOn(grid.rowPinning, 'emit').and.callThrough(); + const row = grid.getRowByIndex(1); + + actionStrip.show(grid.rowList.toArray()[1]); + fixture.detectChanges(); + let pinningIcon = fixture.debugElement.queryAll(By.css(`igx-grid-pinning-actions igx-icon`))[0]; + + pinningIcon.parent.triggerEventHandler('click', new Event('click')); + fixture.detectChanges(); + + expect(grid.rowPinning.emit).toHaveBeenCalledTimes(1); + expect(grid.rowPinning.emit).toHaveBeenCalledWith({ + rowID : row.key, + insertAtIndex: 0, + isPinned: true, + row, + cancel: false + }); + + const row5 = grid.getRowByIndex(4); + actionStrip.show(grid.rowList.toArray()[4]); + fixture.detectChanges(); + pinningIcon = fixture.debugElement.queryAll(By.css(`igx-grid-pinning-actions igx-icon`))[0]; + + pinningIcon.parent.triggerEventHandler('click', new Event('click')); + fixture.detectChanges(); + + expect(grid.rowPinning.emit).toHaveBeenCalledTimes(2); + expect(grid.rowPinning.emit).toHaveBeenCalledWith({ + rowID : row5.key, + insertAtIndex: 1, + isPinned: true, + row: row5, + cancel: false + }); + }); }); describe('auto show/hide', () => { diff --git a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-pinning-actions.component.ts b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-pinning-actions.component.ts index d1f2da10218..b0fac019b2d 100644 --- a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-pinning-actions.component.ts +++ b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-pinning-actions.component.ts @@ -81,7 +81,7 @@ export class IgxGridPinningActionsComponent extends IgxGridActionsBaseDirective } const row = this.strip.context; const grid = row.grid; - grid.pinRow(row.key); + grid.pinRow(row.key, grid.pinnedRecords.length); this.strip.hide(); } diff --git a/projects/igniteui-angular/src/lib/grids/api.service.ts b/projects/igniteui-angular/src/lib/grids/api.service.ts index 94fc690178f..a647c41d106 100644 --- a/projects/igniteui-angular/src/lib/grids/api.service.ts +++ b/projects/igniteui-angular/src/lib/grids/api.service.ts @@ -6,7 +6,7 @@ import { IFilteringExpressionsTree } from '../data-operations/filtering-expressi import { Transaction, TransactionType, State } from '../services/transaction/transaction'; import { IgxCell, IgxGridCRUDService, IgxEditRow } from './common/crud.service'; import { CellType, ColumnType, GridServiceType, GridType, RowType } from './common/grid.interface'; -import { IGridEditEventArgs, IRowToggleEventArgs } from './common/events'; +import { IGridEditEventArgs, IPinRowEventArgs, IRowToggleEventArgs } from './common/events'; import { IgxColumnMovingService } from './moving/moving.service'; import { IGroupingExpression } from '../data-operations/grouping-expression.interface'; import { ISortingExpression, SortingDirection } from '../data-operations/sorting-strategy'; @@ -151,6 +151,15 @@ export class GridBaseAPIService implements GridServiceType { this.grid.validation.update(cell.id.rowID, newRowData); } if (this.grid.primaryKey === cell.column.field) { + if (this.grid.pinnedRecords.length > 0) { + const rowIndex = this.grid.pinnedRecords.indexOf(cell.rowData); + if (rowIndex !== -1) { + const previousRowId = cell.value; + const rowType = this.grid.getRowByIndex(cell.rowIndex); + this.unpin_row(previousRowId, rowType); + this.pin_row(args.newValue, rowIndex, rowType); + } + } if (this.grid.selectionService.isRowSelected(cell.id.rowID)) { this.grid.selectionService.deselectRow(cell.id.rowID); this.grid.selectionService.selectRowById(args.newValue); @@ -542,6 +551,49 @@ export class GridBaseAPIService implements GridServiceType { return DataUtil.sort(cloneArray(data), expressions, this.grid.sortStrategy, this.grid); } + public pin_row(rowID: any, index?: number, row?: RowType): void { + const grid = (this.grid as any); + if (grid._pinnedRecordIDs.indexOf(rowID) !== -1) { + return; + } + const eventArgs = this.get_pin_row_event_args(rowID, index, row, true); + grid.rowPinning.emit(eventArgs); + + if (eventArgs.cancel) { + return; + } + const insertIndex = typeof eventArgs.insertAtIndex === 'number' ? eventArgs.insertAtIndex : grid._pinnedRecordIDs.length; + grid._pinnedRecordIDs.splice(insertIndex, 0, rowID); + } + + public unpin_row(rowID: any, row: RowType): void { + const grid = (this.grid as any); + const index = grid._pinnedRecordIDs.indexOf(rowID); + if (index === -1) { + return; + } + const eventArgs = this.get_pin_row_event_args(rowID, null , row, false); + grid.rowPinning.emit(eventArgs); + + if (eventArgs.cancel) { + return; + } + grid._pinnedRecordIDs.splice(index, 1); + } + + public get_pin_row_event_args(rowID: any, index?: number, row?: RowType, pinned?: boolean) { + const eventArgs: IPinRowEventArgs = { + isPinned: pinned ? true : false, + rowID, + row, + cancel: false + } + if (typeof index === 'number') { + eventArgs.insertAtIndex = index <= this.grid.pinnedRecords.length ? index : this.grid.pinnedRecords.length; + } + return eventArgs; + } + /** * Updates related row of provided grid's data source with provided new row value * diff --git a/projects/igniteui-angular/src/lib/grids/common/grid.interface.ts b/projects/igniteui-angular/src/lib/grids/common/grid.interface.ts index 0537eb92123..f74397a30b6 100644 --- a/projects/igniteui-angular/src/lib/grids/common/grid.interface.ts +++ b/projects/igniteui-angular/src/lib/grids/common/grid.interface.ts @@ -6,7 +6,7 @@ import { IGridEditDoneEventArgs, IRowDataEventArgs, IGridKeydownEventArgs, IRowDragStartEventArgs, IColumnMovingEventArgs, IPinColumnEventArgs, IActiveNodeChangeEventArgs, - ICellPosition, IFilteringEventArgs, IColumnResizeEventArgs, IRowToggleEventArgs, IGridToolbarExportEventArgs + ICellPosition, IFilteringEventArgs, IColumnResizeEventArgs, IRowToggleEventArgs, IGridToolbarExportEventArgs, IPinRowEventArgs } from '../common/events'; import { DisplayDensity, IDensityChangedEventArgs } from '../../core/displayDensity'; import { ChangeDetectorRef, ElementRef, EventEmitter, InjectionToken, QueryList, TemplateRef, ViewContainerRef } from '@angular/core'; @@ -272,6 +272,8 @@ export interface GridServiceType { sort_multiple(expressions: ISortingExpression[]): void; clear_sort(fieldName: string): void; + get_pin_row_event_args(rowID: any, index?: number, row?: RowType , pinned?: boolean): IPinRowEventArgs; + filterDataByExpressions(expressionsTree: IFilteringExpressionsTree): any[]; sortDataByExpressions(data: any[], expressions: ISortingExpression[]): any[]; 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 989853a0d2e..e5e18662051 100644 --- a/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts +++ b/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts @@ -4831,13 +4831,7 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements return false; } - const eventArgs: IPinRowEventArgs = { - insertAtIndex: index, - isPinned: true, - rowID, - row, - cancel: false - }; + const eventArgs = this.gridAPI.get_pin_row_event_args(rowID, index, row, true); this.rowPinning.emit(eventArgs); if (eventArgs.cancel) { @@ -4873,12 +4867,8 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements if (index === -1) { return false; } - const eventArgs: IPinRowEventArgs = { - isPinned: false, - rowID, - row, - cancel: false - }; + + const eventArgs = this.gridAPI.get_pin_row_event_args(rowID, null, row, false); this.rowPinning.emit(eventArgs); if (eventArgs.cancel) { diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid-row-pinning.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid-row-pinning.spec.ts index c5f20791bc7..723e4b25298 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid-row-pinning.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid-row-pinning.spec.ts @@ -176,6 +176,60 @@ describe('Row Pinning #grid', () => { expect(grid.rowPinning.emit).toHaveBeenCalledTimes(2); }); + it('should emit correct rowPinning arguments on pin/unpin.', () => { + spyOn(grid.rowPinning, 'emit').and.callThrough(); + + const row = grid.getRowByIndex(5); + const rowID = row.key; + row.pin(); + + expect(grid.rowPinning.emit).toHaveBeenCalledTimes(1); + expect(grid.rowPinning.emit).toHaveBeenCalledWith({ + rowID, + insertAtIndex: 0, + isPinned: true, + row, + cancel: false + }); + + const row2 = grid.getRowByIndex(3); + const rowID2 = row2.key; + row2.pin(); + + expect(grid.rowPinning.emit).toHaveBeenCalledTimes(2); + expect(grid.rowPinning.emit).toHaveBeenCalledWith({ + rowID: rowID2, + insertAtIndex: 1, + isPinned: true, + row: row2, + cancel: false + }); + }); + + it('should be able to set pin possition of row on pin/unpin events.', () => { + const row1 = grid.getRowByIndex(0); + row1.pin(); + expect(row1.pinned).toBe(true); + expect(grid.pinnedRecords.length).toBe(1); + expect(grid.pinnedRecords[0]).toEqual(row1.data); + + const row2 = grid.getRowByIndex(2); + row2.pin(); + grid.pinRow(row2.key); + expect(row2.pinned).toBe(true); + expect(grid.pinnedRecords.length).toBe(2); + expect(grid.pinnedRecords[1]).toEqual(row2.data); + + grid.rowPinning.subscribe((e: IPinRowEventArgs) => { + e.insertAtIndex = 0; + }); + const row5 = grid.getRowByIndex(5); + row5.pin(); + expect(row2.pinned).toBe(true); + expect(grid.pinnedRecords.length).toBe(3); + expect(grid.pinnedRecords[0]).toEqual(row5.data); + }); + it('should emit rowPinned on pin/unpin.', () => { spyOn(grid.rowPinned, 'emit').and.callThrough();