88
99import {
1010 Component ,
11+ ChangeDetectorRef ,
1112 Input ,
1213 Inject ,
1314 Output ,
@@ -113,7 +114,17 @@ export class MatTabBodyPortal extends CdkPortalOutlet implements OnInit, OnDestr
113114 'class' : 'mat-tab-body' ,
114115 } ,
115116} )
116- export class MatTabBody implements OnInit {
117+ export class MatTabBody implements OnInit , OnDestroy {
118+
119+ /** Current position of the tab-body in the tab-group. Zero means that the tab is visible. */
120+ private _positionIndex : number ;
121+
122+ /** Subscription to the directionality change observable. */
123+ private _dirChangeSubscription = Subscription . EMPTY ;
124+
125+ /** Tab body position state. Used by the animation trigger for the current state. */
126+ _position : MatTabBodyPositionState ;
127+
117128 /** Event emitted when the tab begins to animate towards the center as the active tab. */
118129 @Output ( ) readonly _onCentering : EventEmitter < number > = new EventEmitter < number > ( ) ;
119130
@@ -132,46 +143,45 @@ export class MatTabBody implements OnInit {
132143 /** The tab body content to display. */
133144 @Input ( 'content' ) _content : TemplatePortal ;
134145
146+ /** Position that will be used when the tab is immediately becoming visible after creation. */
147+ @Input ( ) origin : number ;
148+
135149 /** The shifted index position of the tab body, where zero represents the active center tab. */
136150 @Input ( )
137151 set position ( position : number ) {
138- if ( position < 0 ) {
139- this . _position = this . _getLayoutDirection ( ) == 'ltr' ? 'left' : 'right' ;
140- } else if ( position > 0 ) {
141- this . _position = this . _getLayoutDirection ( ) == 'ltr' ? 'right' : 'left' ;
142- } else {
143- this . _position = 'center' ;
144- }
152+ this . _positionIndex = position ;
153+ this . _computePositionAnimationState ( ) ;
145154 }
146- _position : MatTabBodyPositionState ;
147-
148- /** The origin position from which this tab should appear when it is centered into view. */
149- @Input ( )
150- set origin ( origin : number ) {
151- if ( origin == null ) { return ; }
152155
153- const dir = this . _getLayoutDirection ( ) ;
154- if ( ( dir == 'ltr' && origin <= 0 ) || ( dir == 'rtl' && origin > 0 ) ) {
155- this . _origin = 'left' ;
156- } else {
157- this . _origin = 'right' ;
156+ constructor ( private _elementRef : ElementRef ,
157+ @Optional ( ) private _dir : Directionality ,
158+ /**
159+ * @deletion -target 7.0.0 changeDetectorRef to be made required.
160+ */
161+ changeDetectorRef ?: ChangeDetectorRef ) {
162+
163+ if ( this . _dir && changeDetectorRef ) {
164+ this . _dirChangeSubscription = this . _dir . change . subscribe ( dir => {
165+ this . _computePositionAnimationState ( dir ) ;
166+ changeDetectorRef . markForCheck ( ) ;
167+ } ) ;
158168 }
159169 }
160- _origin : MatTabBodyOriginState ;
161-
162- constructor ( private _elementRef : ElementRef ,
163- @Optional ( ) private _dir : Directionality ) { }
164170
165171 /**
166172 * After initialized, check if the content is centered and has an origin. If so, set the
167173 * special position states that transition the tab from the left or right before centering.
168174 */
169175 ngOnInit ( ) {
170- if ( this . _position == 'center' && this . _origin ) {
171- this . _position = this . _origin == 'left' ? 'left-origin-center' : 'right-origin-center' ;
176+ if ( this . _position == 'center' && this . origin !== undefined ) {
177+ this . _position = this . _computePositionFromOrigin ( ) ;
172178 }
173179 }
174180
181+ ngOnDestroy ( ) {
182+ this . _dirChangeSubscription . unsubscribe ( ) ;
183+ }
184+
175185 _onTranslateTabStarted ( e : AnimationEvent ) : void {
176186 const isCentering = this . _isCenterPosition ( e . toState ) ;
177187 this . _beforeCentering . emit ( isCentering ) ;
@@ -202,4 +212,29 @@ export class MatTabBody implements OnInit {
202212 position == 'left-origin-center' ||
203213 position == 'right-origin-center' ;
204214 }
215+
216+ /** Computes the position state that will be used for the tab-body animation trigger. */
217+ private _computePositionAnimationState ( dir : Direction = this . _getLayoutDirection ( ) ) {
218+ if ( this . _positionIndex < 0 ) {
219+ this . _position = dir == 'ltr' ? 'left' : 'right' ;
220+ } else if ( this . _positionIndex > 0 ) {
221+ this . _position = dir == 'ltr' ? 'right' : 'left' ;
222+ } else {
223+ this . _position = 'center' ;
224+ }
225+ }
226+
227+ /**
228+ * Computes the position state based on the specified origin position. This is used if the
229+ * tab is becoming visible immediately after creation.
230+ */
231+ private _computePositionFromOrigin ( ) : MatTabBodyPositionState {
232+ const dir = this . _getLayoutDirection ( ) ;
233+
234+ if ( ( dir == 'ltr' && this . origin <= 0 ) || ( dir == 'rtl' && this . origin > 0 ) ) {
235+ return 'left-origin-center' ;
236+ }
237+
238+ return 'right-origin-center' ;
239+ }
205240}
0 commit comments