Skip to content

Commit 78c4b86

Browse files
committed
fix(material/form-field): add hasFloatingLabel input and update classes if mat-label is added and removed dynamically
Currently, when `mat-Label` is added dynamically initially its not visible in DOM, this fix will add/remove classes for the same. Fixes angular#29939
1 parent dac7bc8 commit 78c4b86

File tree

4 files changed

+38
-10
lines changed

4 files changed

+38
-10
lines changed

goldens/material/form-field/index.api.md

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { NgControl } from '@angular/forms';
1818
import { Observable } from 'rxjs';
1919
import { OnDestroy } from '@angular/core';
2020
import { QueryList } from '@angular/core';
21+
import { SimpleChanges } from '@angular/core';
2122

2223
// @public
2324
export type FloatLabelType = 'always' | 'auto';

goldens/material/input/index.api.md

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { OnChanges } from '@angular/core';
2525
import { OnDestroy } from '@angular/core';
2626
import { Platform } from '@angular/cdk/platform';
2727
import { QueryList } from '@angular/core';
28+
import { SimpleChanges } from '@angular/core';
2829
import { Subject } from 'rxjs';
2930
import { WritableSignal } from '@angular/core';
3031

src/material/form-field/directives/notched-outline.ts

+23-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
ElementRef,
1414
Input,
1515
NgZone,
16+
SimpleChanges,
1617
ViewChild,
1718
ViewEncapsulation,
1819
inject,
@@ -43,15 +44,23 @@ export class MatFormFieldNotchedOutline implements AfterViewInit {
4344
/** Whether the notch should be opened. */
4445
@Input('matFormFieldNotchedOutlineOpen') open: boolean = false;
4546

47+
/** Whether the floating label is present. */
48+
@Input('matFormFieldHasFloatingLabel') hasFloatingLabel: boolean = false;
49+
4650
@ViewChild('notch') _notch: ElementRef;
4751

52+
/** Gets the HTML element for the floating label. */
53+
get element(): HTMLElement {
54+
return this._elementRef.nativeElement;
55+
}
56+
4857
constructor(...args: unknown[]);
4958
constructor() {}
5059

5160
ngAfterViewInit(): void {
52-
const label = this._elementRef.nativeElement.querySelector<HTMLElement>('.mdc-floating-label');
61+
const label = this.element.querySelector<HTMLElement>('.mdc-floating-label');
5362
if (label) {
54-
this._elementRef.nativeElement.classList.add('mdc-notched-outline--upgraded');
63+
this.element.classList.add('mdc-notched-outline--upgraded');
5564

5665
if (typeof requestAnimationFrame === 'function') {
5766
label.style.transitionDuration = '0s';
@@ -60,7 +69,18 @@ export class MatFormFieldNotchedOutline implements AfterViewInit {
6069
});
6170
}
6271
} else {
63-
this._elementRef.nativeElement.classList.add('mdc-notched-outline--no-label');
72+
this.element.classList.add('mdc-notched-outline--no-label');
73+
}
74+
}
75+
76+
ngOnChanges(changes: SimpleChanges) {
77+
if (
78+
changes['hasFloatingLabel'] &&
79+
this.hasFloatingLabel &&
80+
this.element.classList.contains('mdc-notched-outline--no-label')
81+
) {
82+
this.element.classList.add('mdc-notched-outline--upgraded');
83+
this.element.classList.remove('mdc-notched-outline--no-label');
6484
}
6585
}
6686

src/material/form-field/form-field.html

+13-7
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@
5050
}
5151
<div class="mat-mdc-form-field-flex">
5252
@if (_hasOutline()) {
53-
<div matFormFieldNotchedOutline [matFormFieldNotchedOutlineOpen]="_shouldLabelFloat()">
53+
<div
54+
matFormFieldNotchedOutline
55+
[matFormFieldNotchedOutlineOpen]="_shouldLabelFloat()"
56+
[matFormFieldHasFloatingLabel]="_hasFloatingLabel()"
57+
>
5458
@if (!_forceDisplayInfixLabel()) {
5559
<ng-template [ngTemplateOutlet]="labelTemplate"></ng-template>
5660
}
@@ -96,8 +100,8 @@
96100
</div>
97101

98102
<div
99-
class="mat-mdc-form-field-subscript-wrapper mat-mdc-form-field-bottom-align"
100-
[class.mat-mdc-form-field-subscript-dynamic-size]="subscriptSizing === 'dynamic'"
103+
class="mat-mdc-form-field-subscript-wrapper mat-mdc-form-field-bottom-align"
104+
[class.mat-mdc-form-field-subscript-dynamic-size]="subscriptSizing === 'dynamic'"
101105
>
102106
@let subscriptMessageType = _getSubscriptMessageType();
103107

@@ -106,10 +110,12 @@
106110
as having it appear post render will not consistently work. We also do not want to add
107111
additional divs as it causes styling regressions.
108112
-->
109-
<div aria-atomic="true" aria-live="polite"
110-
[class.mat-mdc-form-field-error-wrapper]="subscriptMessageType === 'error'"
111-
[class.mat-mdc-form-field-hint-wrapper]="subscriptMessageType === 'hint'"
112-
>
113+
<div
114+
aria-atomic="true"
115+
aria-live="polite"
116+
[class.mat-mdc-form-field-error-wrapper]="subscriptMessageType === 'error'"
117+
[class.mat-mdc-form-field-hint-wrapper]="subscriptMessageType === 'hint'"
118+
>
113119
@switch (subscriptMessageType) {
114120
@case ('error') {
115121
<ng-content select="mat-error, [matError]"></ng-content>

0 commit comments

Comments
 (0)