@@ -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 ,
@@ -145,14 +144,16 @@ export class MatFormField extends _MatFormFieldMixinBase
145
144
/** The form-field appearance style. */
146
145
@Input ( )
147
146
get appearance ( ) : MatFormFieldAppearance {
148
- return this . _appearance || this . _defaultOptions && this . _defaultOptions . appearance || 'legacy' ;
147
+ return this . _appearance ;
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 ;
150
+ if ( this . _appearance !== value && value === 'outline' ) {
151
+ // The outline gap cannot update until change detection causes the ngIf updates, causing the
152
+ // outline elements to show in the dom. This is a safe action to take because
153
+ // updateOutlineGap does not cause a change detection cycle to run. setTimeout is used
154
+ // because the update needs to be in a a new task rather than the next microtask.
155
+ setTimeout ( ( ) => this . updateOutlineGap ( ) ) ;
154
156
}
155
-
156
157
this . _appearance = value ;
157
158
}
158
159
_appearance : MatFormFieldAppearance ;
@@ -217,17 +218,13 @@ export class MatFormField extends _MatFormFieldMixinBase
217
218
/** Whether the Angular animations are enabled. */
218
219
_animationsEnabled : boolean ;
219
220
220
- _outlineGapWidth = 0 ;
221
- _outlineGapStart = 0 ;
222
- _initialGapCalculated = false ;
223
-
224
221
/**
225
222
* @deprecated
226
223
* @breaking -change 7.0.0
227
224
*/
228
225
@ViewChild ( 'underline' ) underlineRef : ElementRef ;
229
226
230
- @ViewChild ( 'connectionContainer' ) _connectionContainerRef : ElementRef ;
227
+ @ViewChild ( 'connectionContainer' ) _connectionContainerRef : ElementRef < HTMLDivElement > ;
231
228
@ViewChild ( 'inputContainer' ) _inputContainerRef : ElementRef ;
232
229
@ViewChild ( 'label' ) private _label : ElementRef ;
233
230
@ContentChild ( MatFormFieldControl ) _control : MatFormFieldControl < any > ;
@@ -245,15 +242,15 @@ export class MatFormField extends _MatFormFieldMixinBase
245
242
@Optional ( ) private _dir : Directionality ,
246
243
@Optional ( ) @Inject ( MAT_FORM_FIELD_DEFAULT_OPTIONS ) private _defaultOptions :
247
244
MatFormFieldDefaultOptions ,
248
- // @breaking -change 7.0.0 _platform, _ngZone and _animationMode to be made required.
245
+ // @breaking -change 7.0.0 _platform and _animationMode to be made required.
249
246
private _platform ?: Platform ,
250
- private _ngZone ?: NgZone ,
251
247
@Optional ( ) @Inject ( ANIMATION_MODULE_TYPE ) _animationMode ?: string ) {
252
248
super ( _elementRef ) ;
253
249
254
250
this . _labelOptions = labelOptions ? labelOptions : { } ;
255
251
this . floatLabel = this . _labelOptions . float || 'auto' ;
256
252
this . _animationsEnabled = _animationMode !== 'NoopAnimations' ;
253
+ this . appearance = this . _defaultOptions && this . _defaultOptions . appearance || 'outline' ;
257
254
}
258
255
259
256
/**
@@ -298,20 +295,6 @@ export class MatFormField extends _MatFormFieldMixinBase
298
295
299
296
ngAfterContentChecked ( ) {
300
297
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
298
}
316
299
317
300
ngAfterViewInit ( ) {
@@ -422,9 +405,9 @@ export class MatFormField extends _MatFormFieldMixinBase
422
405
let ids : string [ ] = [ ] ;
423
406
424
407
if ( this . _getDisplayedMessages ( ) === 'hint' ) {
425
- let startHint = this . _hintChildren ?
408
+ const startHint = this . _hintChildren ?
426
409
this . _hintChildren . find ( hint => hint . align === 'start' ) : null ;
427
- let endHint = this . _hintChildren ?
410
+ const endHint = this . _hintChildren ?
428
411
this . _hintChildren . find ( hint => hint . align === 'end' ) : null ;
429
412
430
413
if ( startHint ) {
@@ -456,10 +439,19 @@ export class MatFormField extends _MatFormFieldMixinBase
456
439
* appearance.
457
440
*/
458
441
updateOutlineGap ( ) {
459
- if ( this . appearance === 'outline' && this . _label && this . _label . nativeElement . children . length ) {
442
+ if ( this . appearance !== 'outline' ) {
443
+ return ;
444
+ }
445
+
446
+ let startWidth = 0 ;
447
+ let gapWidth = 0 ;
448
+ const startEls = this . _connectionContainerRef . nativeElement . querySelectorAll < HTMLDivElement > (
449
+ '.mat-form-field-outline-start' ) ;
450
+ const gapEls = this . _connectionContainerRef . nativeElement . querySelectorAll < HTMLDivElement > (
451
+ '.mat-form-field-outline-gap' ) ;
452
+ if ( this . _label && this . _label . nativeElement . children . length ) {
460
453
if ( this . _platform && ! this . _platform . isBrowser ) {
461
454
// getBoundingClientRect isn't available on the server.
462
- this . _initialGapCalculated = true ;
463
455
return ;
464
456
}
465
457
if ( ! document . documentElement . contains ( this . _elementRef . nativeElement ) ) {
@@ -474,14 +466,16 @@ export class MatFormField extends _MatFormFieldMixinBase
474
466
for ( const child of this . _label . nativeElement . children ) {
475
467
labelWidth += child . offsetWidth ;
476
468
}
477
- this . _outlineGapStart = labelStart - containerStart - outlineGapPadding ;
478
- this . _outlineGapWidth = labelWidth * floatingLabelScale + outlineGapPadding * 2 ;
479
- } else {
480
- this . _outlineGapStart = 0 ;
481
- this . _outlineGapWidth = 0 ;
469
+ startWidth = labelStart - containerStart - outlineGapPadding ;
470
+ gapWidth = labelWidth * floatingLabelScale + outlineGapPadding * 2 ;
471
+ }
472
+
473
+ for ( let i = 0 ; i < startEls . length ; i ++ ) {
474
+ startEls . item ( i ) . style . width = `${ startWidth } px` ;
475
+ }
476
+ for ( let i = 0 ; i < gapEls . length ; i ++ ) {
477
+ gapEls . item ( i ) . style . width = `${ gapWidth } px` ;
482
478
}
483
- this . _initialGapCalculated = true ;
484
- this . _changeDetectorRef . markForCheck ( ) ;
485
479
}
486
480
487
481
/** Gets the start end of the rect considering the current directionality. */
0 commit comments