@@ -12,7 +12,10 @@ import {
12
12
transition ,
13
13
AnimationTransitionEvent ,
14
14
ElementRef ,
15
- Optional
15
+ Optional ,
16
+ ChangeDetectorRef ,
17
+ AfterViewChecked ,
18
+ AfterContentChecked ,
16
19
} from '@angular/core' ;
17
20
import { TemplatePortal , PortalHostDirective , Dir , LayoutDirection } from '../core' ;
18
21
import 'rxjs/add/operator/map' ;
@@ -65,7 +68,7 @@ export type MdTabBodyOriginState = 'left' | 'right';
65
68
] )
66
69
]
67
70
} )
68
- export class MdTabBody implements OnInit {
71
+ export class MdTabBody implements OnInit , AfterViewChecked , AfterContentChecked {
69
72
/** The portal host inside of this container into which the tab body content will be loaded. */
70
73
@ViewChild ( PortalHostDirective ) _portalHost : PortalHostDirective ;
71
74
@@ -92,6 +95,10 @@ export class MdTabBody implements OnInit {
92
95
}
93
96
}
94
97
98
+ /** Whether the element is allowed to be animated. */
99
+ _canBeAnimated : boolean = false ;
100
+
101
+ /** The origin position from which this tab should appear when it is centered into view. */
95
102
_origin : MdTabBodyOriginState ;
96
103
97
104
/** The origin position from which this tab should appear when it is centered into view. */
@@ -106,7 +113,10 @@ export class MdTabBody implements OnInit {
106
113
}
107
114
}
108
115
109
- constructor ( private _elementRef : ElementRef , @Optional ( ) private _dir : Dir ) { }
116
+ constructor (
117
+ @Optional ( ) private _dir : Dir ,
118
+ private _elementRef : ElementRef ,
119
+ private _changeDetectorRef : ChangeDetectorRef ) { }
110
120
111
121
/**
112
122
* After initialized, check if the content is centered and has an origin. If so, set the
@@ -128,6 +138,28 @@ export class MdTabBody implements OnInit {
128
138
}
129
139
}
130
140
141
+ /**
142
+ * After the content has been checked, determines whether the element should be allowed to
143
+ * animate. This has to be limited, because under a specific set of circumstances (see #2151),
144
+ * the animations can be triggered too early, which either crashes Chrome by putting it into an
145
+ * infinite loop (with Angular < 2.3.0) or throws an error because the element doesn't have a
146
+ * computed style (with Angular > 2.3.0). This can alternatively be determined by checking the
147
+ * transform: canBeAnimated = getComputedStyle(element) !== '', however document.contains should
148
+ * be faster since it doesn't cause a reflow.
149
+ *
150
+ * TODO: This can safely be removed after we stop supporting Angular < 2.4.2. The fix landed via
151
+ * https://github.com/angular/angular/commit/21030e9a1cf30e8101399d8535ed72d847a23ba6
152
+ */
153
+ ngAfterContentChecked ( ) {
154
+ if ( ! this . _canBeAnimated ) {
155
+ this . _canBeAnimated = document . body . contains ( this . _elementRef . nativeElement ) ;
156
+
157
+ if ( this . _canBeAnimated ) {
158
+ this . _changeDetectorRef . markForCheck ( ) ;
159
+ }
160
+ }
161
+ }
162
+
131
163
_onTranslateTabStarted ( e : AnimationTransitionEvent ) {
132
164
if ( this . _isCenterPosition ( e . toState ) ) {
133
165
this . onCentering . emit ( this . _elementRef . nativeElement . clientHeight ) ;
@@ -151,7 +183,6 @@ export class MdTabBody implements OnInit {
151
183
return this . _dir && this . _dir . value === 'rtl' ? 'rtl' : 'ltr' ;
152
184
}
153
185
154
-
155
186
/** Whether the provided position state is considered center, regardless of origin. */
156
187
private _isCenterPosition ( position : MdTabBodyPositionState | string ) : boolean {
157
188
return position == 'center' ||
0 commit comments