11import {
22 Component , ChangeDetectionStrategy , Input , Output , EventEmitter , ContentChild , ViewChildren ,
3- QueryList , ViewChild , ElementRef , TemplateRef , DoCheck , AfterContentInit , HostBinding , forwardRef , OnInit , AfterViewInit
3+ QueryList , ViewChild , ElementRef , TemplateRef , DoCheck , AfterContentInit , HostBinding , forwardRef , OnInit , AfterViewInit , HostListener
44} from '@angular/core' ;
55import { GridBaseAPIService } from '../api.service' ;
66import { IgxGridBaseDirective } from '../grid-base.directive' ;
@@ -347,8 +347,8 @@ export class IgxGridComponent extends IgxGridBaseDirective implements GridType,
347347 }
348348
349349 /**
350- *@hidden
351- */
350+ *@hidden
351+ */
352352 @Output ( )
353353 public groupingExpansionStateChange = new EventEmitter < IGroupByExpandState [ ] > ( ) ;
354354
@@ -553,6 +553,7 @@ export class IgxGridComponent extends IgxGridBaseDirective implements GridType,
553553
554554 private _expansionStates : Map < any , boolean > = new Map < any , boolean > ( ) ;
555555
556+
556557 /**
557558 * Returns a list of key-value pairs [row ID, expansion state]. Includes only states that differ from the default one.
558559 * ```typescript
@@ -571,6 +572,14 @@ export class IgxGridComponent extends IgxGridBaseDirective implements GridType,
571572 @Output ( )
572573 public expansionStatesChange = new EventEmitter < Map < any , boolean > > ( ) ;
573574
575+ /**
576+ *@hidden
577+ */
578+ @Output ( )
579+ private _focusIn = new EventEmitter < any > ( ) ;
580+ @HostListener ( 'focusin' ) onFocusIn ( ) {
581+ this . _focusIn . emit ( ) ;
582+ }
574583
575584 /**
576585 * Sets a list of key-value pairs [row ID, expansion state].
@@ -682,8 +691,21 @@ export class IgxGridComponent extends IgxGridBaseDirective implements GridType,
682691 this . verticalScrollContainer . addScrollTop ( evt . target . scrollTop ) ;
683692 evt . target . scrollTop = 0 ;
684693 this . verticalScrollContainer . onChunkLoad . pipe ( first ( ) ) . subscribe ( ( ) => {
685- // Some browsers (like Edge/IE) lose focus after scrolling.
686- ( activeElem as any ) . focus ( ) ;
694+ const active = this . selectionService . activeElement ;
695+ const currRow = ( this . navigation as any ) . getRowByIndex ( active . row , '' ) ;
696+ // check if the focused element was a child of the details view
697+ if ( this . isDetailRecord ( active . row ) && currRow && currRow . contains ( activeElem ) ) {
698+ // Some browsers (like Edge/IE) lose focus after scrolling even when the element was in the DOM.
699+ ( activeElem as any ) . focus ( { preventScroll : true } ) ;
700+ return ;
701+ }
702+ const nextCellTarget = this . navigation . getCellElementByVisibleIndex ( active . row , active . column ) ;
703+ const nextRowTarget = ( this . navigation as any ) . getRowByIndex ( active . row + 1 , '' ) ;
704+ if ( nextCellTarget ) {
705+ nextCellTarget . focus ( { preventScroll : true } ) ;
706+ } else if ( nextRowTarget ) {
707+ nextRowTarget . focus ( { preventScroll : true } ) ;
708+ }
687709 } ) ;
688710 }
689711 }
@@ -698,6 +720,13 @@ export class IgxGridComponent extends IgxGridBaseDirective implements GridType,
698720 return rec ;
699721 }
700722
723+ public detailsViewFocused ( container , rowIndex ) {
724+ this . selectionService . activeElement = {
725+ row : rowIndex ,
726+ column : this . selectionService . activeElement ? this . selectionService . activeElement . column : 0
727+ } ;
728+ }
729+
701730 public detailsKeyboardHandler ( event , rowIndex , container ) {
702731 const colIndex = this . selectionService . activeElement ? this . selectionService . activeElement . column : 0 ;
703732 const shift = event . shiftKey ;
@@ -706,12 +735,20 @@ export class IgxGridComponent extends IgxGridBaseDirective implements GridType,
706735 const target = event . target ;
707736 if ( key === 'tab' ) {
708737 event . stopPropagation ( ) ;
738+ const lastColIndex = this . unpinnedColumns [ this . unpinnedColumns . length - 1 ] . visibleIndex ;
709739 if ( shift && target === container ) {
710740 // shift + tab from details to data row
711741 event . preventDefault ( ) ;
712- const lastColIndex = this . unpinnedColumns [ this . unpinnedColumns . length - 1 ] . visibleIndex ;
713742 this . navigateTo ( rowIndex - 1 , lastColIndex ,
714743 ( args ) => args . target . nativeElement . focus ( ) ) ;
744+ } else if ( ! shift ) {
745+ // when the next element is focused via tab check if it is an element outside the details view
746+ // if so we have exited the details view and focus should move to the first cell in the next row
747+ this . _focusIn . pipe ( first ( ) ) . subscribe ( ( ) => {
748+ if ( ! container . contains ( document . activeElement ) ) {
749+ this . navigation . performTab ( container , { row : rowIndex , column : lastColIndex } ) ;
750+ }
751+ } ) ;
715752 }
716753 } else if ( key === 'arrowup' && ! ctrl && target === container ) {
717754 this . navigation . navigateUp ( container , { row : rowIndex , column : colIndex } ) ;
0 commit comments