@@ -21,7 +21,6 @@ import {
21
21
Inject ,
22
22
InjectionToken ,
23
23
Input ,
24
- NgZone ,
25
24
Optional ,
26
25
QueryList ,
27
26
ViewChild ,
@@ -148,12 +147,13 @@ export class MatFormField extends _MatFormFieldMixinBase
148
147
return this . _appearance || this . _defaultOptions && this . _defaultOptions . appearance || 'legacy' ;
149
148
}
150
149
set appearance ( value : MatFormFieldAppearance ) {
151
- // If we're switching to `outline` from another appearance, we have to recalculate the gap.
152
- if ( value !== this . _appearance && value === 'outline' ) {
153
- this . _initialGapCalculated = false ;
154
- }
155
-
156
150
this . _appearance = value ;
151
+ if ( value === 'outline' ) {
152
+ // The outline gap cannot update until change detection causes the ngIf updates, causing the
153
+ // outline elements to show in the dom. This is a safe action to take because
154
+ // updateOutlineGap does not cause a change detection cycle to run.
155
+ Promise . resolve ( ) . then ( ( ) => this . updateOutlineGap ( ) ) ;
156
+ }
157
157
}
158
158
_appearance : MatFormFieldAppearance ;
159
159
@@ -217,17 +217,13 @@ export class MatFormField extends _MatFormFieldMixinBase
217
217
/** Whether the Angular animations are enabled. */
218
218
_animationsEnabled : boolean ;
219
219
220
- _outlineGapWidth = 0 ;
221
- _outlineGapStart = 0 ;
222
- _initialGapCalculated = false ;
223
-
224
220
/**
225
221
* @deprecated
226
222
* @breaking -change 7.0.0
227
223
*/
228
224
@ViewChild ( 'underline' ) underlineRef : ElementRef ;
229
225
230
- @ViewChild ( 'connectionContainer' ) _connectionContainerRef : ElementRef ;
226
+ @ViewChild ( 'connectionContainer' ) _connectionContainerRef : ElementRef < HTMLDivElement > ;
231
227
@ViewChild ( 'inputContainer' ) _inputContainerRef : ElementRef ;
232
228
@ViewChild ( 'label' ) private _label : ElementRef ;
233
229
@ContentChild ( MatFormFieldControl ) _control : MatFormFieldControl < any > ;
@@ -245,9 +241,8 @@ export class MatFormField extends _MatFormFieldMixinBase
245
241
@Optional ( ) private _dir : Directionality ,
246
242
@Optional ( ) @Inject ( MAT_FORM_FIELD_DEFAULT_OPTIONS ) private _defaultOptions :
247
243
MatFormFieldDefaultOptions ,
248
- // @breaking -change 7.0.0 _platform, _ngZone and _animationMode to be made required.
244
+ // @breaking -change 7.0.0 _platform and _animationMode to be made required.
249
245
private _platform ?: Platform ,
250
- private _ngZone ?: NgZone ,
251
246
@Optional ( ) @Inject ( ANIMATION_MODULE_TYPE ) _animationMode ?: string ) {
252
247
super ( _elementRef ) ;
253
248
@@ -298,26 +293,13 @@ export class MatFormField extends _MatFormFieldMixinBase
298
293
299
294
ngAfterContentChecked ( ) {
300
295
this . _validateControlChild ( ) ;
301
-
302
- if ( ! this . _initialGapCalculated ) {
303
- // @breaking -change 7.0.0 Remove this check and else block once _ngZone is required.
304
- if ( this . _ngZone ) {
305
- // It's important that we run this outside the `_ngZone`, because the `Promise.resolve`
306
- // can kick us into an infinite change detection loop, if the `_initialGapCalculated`
307
- // wasn't flipped on for some reason.
308
- this . _ngZone . runOutsideAngular ( ( ) => {
309
- Promise . resolve ( ) . then ( ( ) => this . updateOutlineGap ( ) ) ;
310
- } ) ;
311
- } else {
312
- Promise . resolve ( ) . then ( ( ) => this . updateOutlineGap ( ) ) ;
313
- }
314
- }
315
296
}
316
297
317
298
ngAfterViewInit ( ) {
318
299
// Avoid animations on load.
319
300
this . _subscriptAnimationState = 'enter' ;
320
301
this . _changeDetectorRef . detectChanges ( ) ;
302
+ this . updateOutlineGap ( ) ;
321
303
}
322
304
323
305
/** Determines whether a class from the NgControl should be forwarded to the host element. */
@@ -422,9 +404,9 @@ export class MatFormField extends _MatFormFieldMixinBase
422
404
let ids : string [ ] = [ ] ;
423
405
424
406
if ( this . _getDisplayedMessages ( ) === 'hint' ) {
425
- let startHint = this . _hintChildren ?
407
+ const startHint = this . _hintChildren ?
426
408
this . _hintChildren . find ( hint => hint . align === 'start' ) : null ;
427
- let endHint = this . _hintChildren ?
409
+ const endHint = this . _hintChildren ?
428
410
this . _hintChildren . find ( hint => hint . align === 'end' ) : null ;
429
411
430
412
if ( startHint ) {
@@ -456,10 +438,19 @@ export class MatFormField extends _MatFormFieldMixinBase
456
438
* appearance.
457
439
*/
458
440
updateOutlineGap ( ) {
459
- if ( this . appearance === 'outline' && this . _label && this . _label . nativeElement . children . length ) {
441
+ if ( this . appearance !== 'outline' ) {
442
+ return ;
443
+ }
444
+
445
+ let startWidth = 0 ;
446
+ let gapWidth = 0 ;
447
+ const startEls = this . _connectionContainerRef . nativeElement . querySelectorAll < HTMLDivElement > (
448
+ '.mat-form-field-outline-start' ) ;
449
+ const gapEls = this . _connectionContainerRef . nativeElement . querySelectorAll < HTMLDivElement > (
450
+ '.mat-form-field-outline-gap' ) ;
451
+ if ( this . _label && this . _label . nativeElement . children . length ) {
460
452
if ( this . _platform && ! this . _platform . isBrowser ) {
461
453
// getBoundingClientRect isn't available on the server.
462
- this . _initialGapCalculated = true ;
463
454
return ;
464
455
}
465
456
if ( ! document . documentElement . contains ( this . _elementRef . nativeElement ) ) {
@@ -474,14 +465,16 @@ export class MatFormField extends _MatFormFieldMixinBase
474
465
for ( const child of this . _label . nativeElement . children ) {
475
466
labelWidth += child . offsetWidth ;
476
467
}
477
- this . _outlineGapStart = labelStart - containerStart - outlineGapPadding ;
478
- this . _outlineGapWidth = labelWidth * floatingLabelScale + outlineGapPadding * 2 ;
479
- } else {
480
- this . _outlineGapStart = 0 ;
481
- this . _outlineGapWidth = 0 ;
468
+ startWidth = labelStart - containerStart - outlineGapPadding ;
469
+ gapWidth = labelWidth * floatingLabelScale + outlineGapPadding * 2 ;
470
+ }
471
+
472
+ for ( let i = 0 ; i < startEls . length ; i ++ ) {
473
+ startEls . item ( i ) . style . width = `${ startWidth } px` ;
474
+ }
475
+ for ( let i = 0 ; i < gapEls . length ; i ++ ) {
476
+ gapEls . item ( i ) . style . width = `${ gapWidth } px` ;
482
477
}
483
- this . _initialGapCalculated = true ;
484
- this . _changeDetectorRef . markForCheck ( ) ;
485
478
}
486
479
487
480
/** Gets the start end of the rect considering the current directionality. */
0 commit comments