@@ -18,6 +18,7 @@ import {
18
18
Input ,
19
19
Optional ,
20
20
ViewEncapsulation ,
21
+ OnInit ,
21
22
} from '@angular/core' ;
22
23
import { CanColor , CanColorCtor , mixinColor } from '@angular/material/core' ;
23
24
import { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations' ;
@@ -123,7 +124,7 @@ const INDETERMINATE_ANIMATION_TEMPLATE = `
123
124
changeDetection : ChangeDetectionStrategy . OnPush ,
124
125
encapsulation : ViewEncapsulation . None ,
125
126
} )
126
- export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements CanColor {
127
+ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements OnInit , CanColor {
127
128
private _diameter = BASE_SIZE ;
128
129
private _value = 0 ;
129
130
private _strokeWidth : number ;
@@ -153,13 +154,9 @@ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements
153
154
set diameter ( size : number ) {
154
155
this . _diameter = coerceNumberProperty ( size ) ;
155
156
156
- if ( ! this . _fallbackAnimation ) {
157
- const trackedDiameters = MatProgressSpinner . _diameters ;
158
- const diametersForElement = trackedDiameters . get ( this . _styleRoot ) ;
159
-
160
- if ( ! diametersForElement || ! diametersForElement . has ( this . _diameter ) ) {
161
- this . _attachStyleNode ( ) ;
162
- }
157
+ // If this is set before `ngOnInit`, the style root may not have been resolved yet.
158
+ if ( ! this . _fallbackAnimation && this . _styleRoot ) {
159
+ this . _attachStyleNode ( ) ;
163
160
}
164
161
}
165
162
@@ -201,7 +198,6 @@ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements
201
198
trackedDiameters . set ( _document . head , new Set < number > ( [ BASE_SIZE ] ) ) ;
202
199
}
203
200
204
- this . _styleRoot = _getShadowRoot ( _elementRef . nativeElement , _document ) || _document . head ;
205
201
this . _fallbackAnimation = platform . EDGE || platform . TRIDENT ;
206
202
this . _noopAnimations = animationMode === 'NoopAnimations' &&
207
203
( ! ! defaults && ! defaults . _forceAnimations ) ;
@@ -215,13 +211,23 @@ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements
215
211
this . strokeWidth = defaults . strokeWidth ;
216
212
}
217
213
}
214
+ }
215
+
216
+ ngOnInit ( ) {
217
+ const element = this . _elementRef . nativeElement ;
218
+
219
+ // Note that we need to look up the root node in ngOnInit, rather than the constructor, because
220
+ // Angular seems to create the element outside the shadow root and then moves it inside, if the
221
+ // node is inside an `ngIf` and a ShadowDom-encapsulated component.
222
+ this . _styleRoot = _getShadowRoot ( element , this . _document ) || this . _document . head ;
223
+ this . _attachStyleNode ( ) ;
218
224
219
225
// On IE and Edge, we can't animate the `stroke-dashoffset`
220
226
// reliably so we fall back to a non-spec animation.
221
227
const animationClass =
222
228
`mat-progress-spinner-indeterminate${ this . _fallbackAnimation ? '-fallback' : '' } -animation` ;
223
229
224
- _elementRef . nativeElement . classList . add ( animationClass ) ;
230
+ element . classList . add ( animationClass ) ;
225
231
}
226
232
227
233
/** The radius of the spinner, adjusted for stroke width. */
@@ -261,22 +267,24 @@ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements
261
267
262
268
/** Dynamically generates a style tag containing the correct animation for this diameter. */
263
269
private _attachStyleNode ( ) : void {
264
- const styleTag : HTMLStyleElement = this . _document . createElement ( 'style' ) ;
265
270
const styleRoot = this . _styleRoot ;
266
271
const currentDiameter = this . _diameter ;
267
272
const diameters = MatProgressSpinner . _diameters ;
268
273
let diametersForElement = diameters . get ( styleRoot ) ;
269
274
270
- styleTag . setAttribute ( 'mat-spinner-animation' , currentDiameter + '' ) ;
271
- styleTag . textContent = this . _getAnimationText ( ) ;
272
- styleRoot . appendChild ( styleTag ) ;
275
+ if ( ! diametersForElement || ! diametersForElement . has ( currentDiameter ) ) {
276
+ const styleTag : HTMLStyleElement = this . _document . createElement ( 'style' ) ;
277
+ styleTag . setAttribute ( 'mat-spinner-animation' , currentDiameter + '' ) ;
278
+ styleTag . textContent = this . _getAnimationText ( ) ;
279
+ styleRoot . appendChild ( styleTag ) ;
273
280
274
- if ( ! diametersForElement ) {
275
- diametersForElement = new Set < number > ( ) ;
276
- diameters . set ( styleRoot , diametersForElement ) ;
277
- }
281
+ if ( ! diametersForElement ) {
282
+ diametersForElement = new Set < number > ( ) ;
283
+ diameters . set ( styleRoot , diametersForElement ) ;
284
+ }
278
285
279
- diametersForElement . add ( currentDiameter ) ;
286
+ diametersForElement . add ( currentDiameter ) ;
287
+ }
280
288
}
281
289
282
290
/** Generates animation styles adjusted for the spinner's diameter. */
0 commit comments