@@ -18,6 +18,7 @@ import {
1818 Input ,
1919 Optional ,
2020 ViewEncapsulation ,
21+ OnInit ,
2122} from '@angular/core' ;
2223import { CanColor , CanColorCtor , mixinColor } from '@angular/material/core' ;
2324import { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations' ;
@@ -123,7 +124,7 @@ const INDETERMINATE_ANIMATION_TEMPLATE = `
123124 changeDetection : ChangeDetectionStrategy . OnPush ,
124125 encapsulation : ViewEncapsulation . None ,
125126} )
126- export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements CanColor {
127+ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements OnInit , CanColor {
127128 private _diameter = BASE_SIZE ;
128129 private _value = 0 ;
129130 private _strokeWidth : number ;
@@ -153,13 +154,9 @@ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements
153154 set diameter ( size : number ) {
154155 this . _diameter = coerceNumberProperty ( size ) ;
155156
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 ( ) ;
163160 }
164161 }
165162
@@ -201,7 +198,6 @@ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements
201198 trackedDiameters . set ( _document . head , new Set < number > ( [ BASE_SIZE ] ) ) ;
202199 }
203200
204- this . _styleRoot = _getShadowRoot ( _elementRef . nativeElement , _document ) || _document . head ;
205201 this . _fallbackAnimation = platform . EDGE || platform . TRIDENT ;
206202 this . _noopAnimations = animationMode === 'NoopAnimations' &&
207203 ( ! ! defaults && ! defaults . _forceAnimations ) ;
@@ -215,13 +211,23 @@ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements
215211 this . strokeWidth = defaults . strokeWidth ;
216212 }
217213 }
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 ( ) ;
218224
219225 // On IE and Edge, we can't animate the `stroke-dashoffset`
220226 // reliably so we fall back to a non-spec animation.
221227 const animationClass =
222228 `mat-progress-spinner-indeterminate${ this . _fallbackAnimation ? '-fallback' : '' } -animation` ;
223229
224- _elementRef . nativeElement . classList . add ( animationClass ) ;
230+ element . classList . add ( animationClass ) ;
225231 }
226232
227233 /** The radius of the spinner, adjusted for stroke width. */
@@ -261,22 +267,24 @@ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements
261267
262268 /** Dynamically generates a style tag containing the correct animation for this diameter. */
263269 private _attachStyleNode ( ) : void {
264- const styleTag : HTMLStyleElement = this . _document . createElement ( 'style' ) ;
265270 const styleRoot = this . _styleRoot ;
266271 const currentDiameter = this . _diameter ;
267272 const diameters = MatProgressSpinner . _diameters ;
268273 let diametersForElement = diameters . get ( styleRoot ) ;
269274
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 ) ;
273280
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+ }
278285
279- diametersForElement . add ( currentDiameter ) ;
286+ diametersForElement . add ( currentDiameter ) ;
287+ }
280288 }
281289
282290 /** Generates animation styles adjusted for the spinner's diameter. */
0 commit comments