@@ -18,6 +18,8 @@ import {
18
18
AfterViewChecked ,
19
19
ViewEncapsulation ,
20
20
ChangeDetectionStrategy ,
21
+ OnChanges ,
22
+ SimpleChanges ,
21
23
} from '@angular/core' ;
22
24
import {
23
25
trigger ,
@@ -65,6 +67,7 @@ export type MdTabBodyOriginState = 'left' | 'right';
65
67
changeDetection : ChangeDetectionStrategy . OnPush ,
66
68
host : {
67
69
'class' : 'mat-tab-body' ,
70
+ '[class.mat-tab-body-active]' : 'active' ,
68
71
} ,
69
72
animations : [
70
73
trigger ( 'translateTab' , [
@@ -87,18 +90,27 @@ export type MdTabBodyOriginState = 'left' | 'right';
87
90
] )
88
91
]
89
92
} )
90
- export class MdTabBody implements OnInit , AfterViewChecked {
93
+ export class MdTabBody implements OnInit , OnChanges , AfterViewChecked {
91
94
/** The portal host inside of this container into which the tab body content will be loaded. */
92
95
@ViewChild ( PortalHostDirective ) _portalHost : PortalHostDirective ;
93
96
97
+ /** Element wrapping the tab's content. */
98
+ @ViewChild ( 'content' ) _contentElement : ElementRef ;
99
+
94
100
/** Event emitted when the tab begins to animate towards the center as the active tab. */
95
101
@Output ( ) onCentering : EventEmitter < number > = new EventEmitter < number > ( ) ;
96
102
97
103
/** Event emitted when the tab completes its animation towards the center. */
98
104
@Output ( ) onCentered : EventEmitter < void > = new EventEmitter < void > ( true ) ;
99
105
100
106
/** The tab body content to display. */
101
- @Input ( 'content' ) _content : TemplatePortal < any > ;
107
+ @Input ( 'content' ) _contentPortal : TemplatePortal < any > ;
108
+
109
+ /** Whether the tab is currently active. */
110
+ @Input ( ) active : boolean ;
111
+
112
+ /** Scroll position of the tab before the user switched away. */
113
+ private _lastScrollPosition = 0 ;
102
114
103
115
/** The shifted index position of the tab body, where zero represents the active center tab. */
104
116
_position : MdTabBodyPositionState ;
@@ -146,7 +158,25 @@ export class MdTabBody implements OnInit, AfterViewChecked {
146
158
*/
147
159
ngAfterViewChecked ( ) {
148
160
if ( this . _isCenterPosition ( this . _position ) && ! this . _portalHost . hasAttached ( ) ) {
149
- this . _portalHost . attach ( this . _content ) ;
161
+ this . _portalHost . attach ( this . _contentPortal ) ;
162
+
163
+ if ( this . _lastScrollPosition ) {
164
+ // Depending on the browser, the scrollable element can end up being
165
+ // either the host element or the element with all the content.
166
+ this . _contentElement . nativeElement . scrollTop =
167
+ this . _elementRef . nativeElement . scrollTop =
168
+ this . _lastScrollPosition ;
169
+ }
170
+ }
171
+ }
172
+
173
+ ngOnChanges ( changes : SimpleChanges ) {
174
+ // Cache the scroll position before moving away from the tab. Note that this has to be done
175
+ // through change detection and as early as possible, because some browsers (namely Safari)
176
+ // will reset the scroll position when we switch from an absolute to a relative position.
177
+ if ( changes . active && changes . active . previousValue ) {
178
+ this . _lastScrollPosition = this . _elementRef . nativeElement . scrollTop ||
179
+ this . _contentElement . nativeElement . scrollTop ;
150
180
}
151
181
}
152
182
@@ -176,7 +206,7 @@ export class MdTabBody implements OnInit, AfterViewChecked {
176
206
/** Whether the provided position state is considered center, regardless of origin. */
177
207
private _isCenterPosition ( position : MdTabBodyPositionState | string ) : boolean {
178
208
return position == 'center' ||
179
- position == 'left-origin-center' ||
180
- position == 'right-origin-center' ;
209
+ position == 'left-origin-center' ||
210
+ position == 'right-origin-center' ;
181
211
}
182
212
}
0 commit comments