@@ -27,6 +27,7 @@ export interface IActiveNode {
2727export class IgxGridNavigationService {
2828 public grid : IgxGridBaseDirective & GridType ;
2929 public _activeNode : IActiveNode = { } as IActiveNode ;
30+ public lastActiveNode : IActiveNode = { } as IActiveNode ;
3031 protected pendingNavigation = false ;
3132
3233 public get activeNode ( ) {
@@ -39,6 +40,7 @@ export class IgxGridNavigationService {
3940
4041 handleNavigation ( event : KeyboardEvent ) {
4142 const key = event . key . toLowerCase ( ) ;
43+ if ( this . grid . crudService . cell && NAVIGATION_KEYS . has ( key ) ) { return ; }
4244 if ( event . repeat && SUPPORTED_KEYS . has ( key ) || ( key === 'tab' && this . grid . crudService . cell ) ) {
4345 event . preventDefault ( ) ;
4446 }
@@ -65,8 +67,6 @@ export class IgxGridNavigationService {
6567 if ( [ ' ' , 'spacebar' , 'space' ] . indexOf ( key ) === - 1 ) {
6668 this . grid . selectionService . keyboardStateOnKeydown ( this . activeNode , shift , shift && key === 'tab' ) ;
6769 }
68- if ( this . grid . crudService . cell && NAVIGATION_KEYS . has ( key ) ) { return ; }
69-
7070 const position = this . getNextPosition ( this . activeNode . row , this . activeNode . column , key , shift , ctrl , event ) ;
7171 if ( NAVIGATION_KEYS . has ( key ) ) {
7272 event . preventDefault ( ) ;
@@ -222,23 +222,37 @@ export class IgxGridNavigationService {
222222 const gridRows = this . grid . verticalScrollContainer . totalItemCount ?? this . grid . dataView . length ;
223223 if ( gridRows < 1 ) { this . activeNode = null ; return ; }
224224 if ( ! Object . keys ( this . activeNode ) . length || this . activeNode . row < 0 || this . activeNode . row > gridRows - 1 ) {
225- this . grid . navigateTo ( 0 , 0 , ( obj ) => {
225+ const hasLastActiveNode = Object . keys ( this . lastActiveNode ) . length ;
226+ const shouldClearSelection = hasLastActiveNode && ( this . lastActiveNode . row < 0 || this . lastActiveNode . row > gridRows - 1 ) ;
227+ this . setActiveNode ( this . lastActiveNode . row >= 0 && this . lastActiveNode . row < gridRows ?
228+ this . firstVisibleNode ( this . lastActiveNode . row ) : this . firstVisibleNode ( ) ) ;
229+ if ( shouldClearSelection ) {
226230 this . grid . clearCellSelection ( ) ;
227- obj . target . activate ( event ) ;
228- } ) ;
231+ this . grid . navigateTo ( this . activeNode . row , this . activeNode . column , ( obj ) => {
232+ obj . target ?. activate ( event ) ;
233+ this . grid . cdr . detectChanges ( ) ;
234+ } ) ;
235+ } else {
236+ const range = { rowStart : this . activeNode . row , rowEnd : this . activeNode . row ,
237+ columnStart : this . activeNode . column , columnEnd : this . activeNode . column } ;
238+ this . grid . selectRange ( range ) ;
239+ this . grid . notifyChanges ( ) ;
240+ }
229241 }
230242 }
231243
232244 focusFirstCell ( header = true ) {
233245 if ( ( header || this . grid . dataView . length ) && this . activeNode &&
234246 ( this . activeNode . row === - 1 || this . activeNode . row === this . grid . dataView . length ||
235247 ( ! header && ! this . grid . hasSummarizedColumns ) ) ) { return ; }
248+ const shouldScrollIntoView = this . lastActiveNode && ( header && this . lastActiveNode . row !== - 1 ) ||
249+ ( ! header && this . lastActiveNode . row !== this . grid . dataView . length ) ;
250+ this . setActiveNode ( this . firstVisibleNode ( header ? - 1 : this . grid . dataView . length ) ) ;
251+ if ( shouldScrollIntoView ) {
252+ this . performHorizontalScrollToCell ( this . activeNode . column ) ;
253+ }
254+ this . grid . notifyChanges ( ) ;
236255
237- this . setActiveNode ( {
238- row : header ? - 1 : this . grid . dataView . length , column : 0 ,
239- level : this . grid . hasColumnLayouts ? 1 : 0 , mchCache : { level : 0 , visibleIndex : 0 }
240- } ) ;
241- this . performHorizontalScrollToCell ( 0 ) ;
242256 }
243257
244258 get lastColumnIndex ( ) {
@@ -253,6 +267,19 @@ export class IgxGridNavigationService {
253267 get containerTopOffset ( ) {
254268 return parseInt ( this . grid . verticalScrollContainer . dc . instance . _viewContainer . element . nativeElement . style . top , 10 ) ;
255269 }
270+ private firstVisibleNode ( rowIndex ?) {
271+ const colIndex = this . lastActiveNode . column !== undefined ? this . lastActiveNode . column :
272+ this . grid . visibleColumns . sort ( ( c1 , c2 ) => c1 . visibleIndex - c2 . visibleIndex )
273+ . find ( c => this . isColumnFullyVisible ( c . visibleIndex ) ) ?. visibleIndex ;
274+ const column = this . grid . visibleColumns . find ( ( col ) => ! col . columnLayout && col . visibleIndex === colIndex ) ;
275+ const rowInd = rowIndex ? rowIndex : this . grid . rowList . find ( r => ! this . shouldPerformVerticalScroll ( r . index , colIndex ) ) ?. index ;
276+ const node = { row : rowInd ?? 0 ,
277+ column : column ?. visibleIndex ?? 0 , level : column ?. level ?? 0 ,
278+ mchCache : column ? { level : column . level , visibleIndex : column . visibleIndex } : { } as ColumnGroupsCache ,
279+ layout : column && column . columnLayoutChild ? { rowStart : column . rowStart , colStart : column . colStart ,
280+ rowEnd : column . rowEnd , colEnd : column . colEnd , columnVisibleIndex : column . visibleIndex } : null } ;
281+ return node ;
282+ }
256283
257284 public isColumnFullyVisible ( columnIndex : number ) {
258285 if ( columnIndex < 0 || this . isColumnPinned ( columnIndex , this . forOfDir ( ) ) ) {
0 commit comments