Skip to content

Commit a361f31

Browse files
committed
fix: address feedback
1 parent fae4171 commit a361f31

File tree

5 files changed

+38
-26
lines changed

5 files changed

+38
-26
lines changed

src/cdk/observers/private/BUILD.bazel

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ ng_module(
1515
),
1616
deps = [
1717
"//src:dev_mode_types",
18-
"//src/cdk/platform",
1918
"@npm//rxjs",
2019
],
2120
)

src/cdk/observers/private/shared-resize-observer.ts

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import {inject, Injectable, NgZone, OnDestroy} from '@angular/core';
99
import {Observable, Subject} from 'rxjs';
1010
import {filter, shareReplay, takeUntil} from 'rxjs/operators';
11-
import {Platform} from '@angular/cdk/platform';
1211

1312
/**
1413
* Handler that logs "ResizeObserver loop limit exceeded" errors.
@@ -40,10 +39,8 @@ class SingleBoxSharedResizeObserver {
4039
constructor(
4140
/** The box type to observe for resizes. */
4241
private _box: ResizeObserverBoxOptions,
43-
/** The platform. */
44-
platform: Platform,
4542
) {
46-
if (platform.isBrowser) {
43+
if (typeof ResizeObserver !== 'undefined') {
4744
this._resizeObserver = new ResizeObserver(entries => this._resizeSubject.next(entries));
4845
}
4946
}
@@ -58,16 +55,15 @@ class SingleBoxSharedResizeObserver {
5855
this._elementObservables.set(
5956
target,
6057
new Observable<ResizeObserverEntry[]>(observer => {
61-
const subscription = this._resizeSubject
62-
.pipe(filter(entries => entries.some(entry => entry.target === target)))
63-
.subscribe(observer);
58+
const subscription = this._resizeSubject.subscribe(observer);
6459
this._resizeObserver?.observe(target, {box: this._box});
6560
return () => {
6661
this._resizeObserver?.unobserve(target);
6762
subscription.unsubscribe();
6863
this._elementObservables.delete(target);
6964
};
7065
}).pipe(
66+
filter(entries => entries.some(entry => entry.target === target)),
7167
// Share a replay of the last event so that subsequent calls to observe the same element
7268
// receive initial sizing info like the first one. Also enable ref counting so the
7369
// element will be automatically unobserved when there are no more subscriptions.
@@ -108,11 +104,8 @@ export class SharedResizeObserver implements OnDestroy {
108104
/** The Angular zone. */
109105
private _ngZone = inject(NgZone);
110106

111-
/** The platform. */
112-
private _platform = inject(Platform);
113-
114107
constructor() {
115-
if (this._platform.isBrowser && (typeof ngDevMode === 'undefined' || ngDevMode)) {
108+
if (typeof ResizeObserver !== 'undefined' && (typeof ngDevMode === 'undefined' || ngDevMode)) {
116109
this._ngZone.runOutsideAngular(() => {
117110
window.addEventListener('error', loopLimitExceededErrorHandler);
118111
});
@@ -124,7 +117,7 @@ export class SharedResizeObserver implements OnDestroy {
124117
observer.destroy();
125118
}
126119
this._observers.clear();
127-
if (this._platform.isBrowser && (typeof ngDevMode === 'undefined' || ngDevMode)) {
120+
if (typeof ResizeObserver !== 'undefined' && (typeof ngDevMode === 'undefined' || ngDevMode)) {
128121
window.removeEventListener('error', loopLimitExceededErrorHandler);
129122
}
130123
}
@@ -138,7 +131,7 @@ export class SharedResizeObserver implements OnDestroy {
138131
observe(target: Element, options?: ResizeObserverOptions): Observable<ResizeObserverEntry[]> {
139132
const box = options?.box || 'content-box';
140133
if (!this._observers.has(box)) {
141-
this._observers.set(box, new SingleBoxSharedResizeObserver(box, this._platform));
134+
this._observers.set(box, new SingleBoxSharedResizeObserver(box));
142135
}
143136
return this._observers.get(box)!.observe(target);
144137
}

src/material/form-field/directives/floating-label.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,23 @@
99
import {
1010
Directive,
1111
ElementRef,
12-
EventEmitter,
1312
inject,
1413
Input,
1514
NgZone,
1615
OnDestroy,
17-
Output,
16+
InjectionToken,
1817
} from '@angular/core';
1918
import {SharedResizeObserver} from '@angular/cdk/observers/private';
2019
import {Subscription} from 'rxjs';
2120

21+
/** An interface that the parent form-field should implement to receive resize events. */
22+
export interface FloatingLabelParent {
23+
_handleLabelResized(): void;
24+
}
25+
26+
/** An injion token for the parent form-field. */
27+
export const FLOATING_LABEL_PARENT = new InjectionToken<FloatingLabelParent>('FloatingLabelParent');
28+
2229
/**
2330
* Internal directive that maintains a MDC floating label. This directive does not
2431
* use the `MDCFloatingLabelFoundation` class, as it is not worth the size cost of
@@ -48,7 +55,7 @@ export class MatFormFieldFloatingLabel implements OnDestroy {
4855
set floating(value: boolean) {
4956
this._floating = value;
5057
if (this.monitorResize) {
51-
this.resized.emit();
58+
this._handleResize();
5259
}
5360
}
5461
private _floating = false;
@@ -68,15 +75,15 @@ export class MatFormFieldFloatingLabel implements OnDestroy {
6875
}
6976
private _monitorResize = false;
7077

71-
/** Emits when the label is resized (if resize events are being monitored). */
72-
@Output() resized = new EventEmitter<void>();
73-
7478
/** The shared ResizeObserver. */
7579
private _resizeObserver = inject(SharedResizeObserver);
7680

7781
/** The Angular zone. */
7882
private _ngZone = inject(NgZone);
7983

84+
/** The parent form-field. */
85+
private _parent = inject(FLOATING_LABEL_PARENT);
86+
8087
/** The current resize event subscription. */
8188
private _resizeSubscription = new Subscription();
8289

@@ -106,7 +113,9 @@ export class MatFormFieldFloatingLabel implements OnDestroy {
106113
// This is expected, but If we allow this to all happen within the same macro task it causes an
107114
// error: `ResizeObserver loop limit exceeded`. Therefore we push the notch resize out until
108115
// the next macro task.
109-
setTimeout(() => this.resized.emit());
116+
this._ngZone.runOutsideAngular(() => {
117+
setTimeout(() => this._parent._handleLabelResized());
118+
});
110119
}
111120

112121
/** Subscribes to resize events. */

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@
2020
*ngIf="_hasFloatingLabel()"
2121
[id]="_labelId"
2222
[attr.for]="_control.id"
23-
[attr.aria-owns]="_control.id"
24-
(resized)="_refreshOutlineNotchWidth()">
23+
[attr.aria-owns]="_control.id">
2524
<ng-content select="mat-label"></ng-content>
2625
<!--
2726
We set the required marker as a separate element, in order to make it easier to target if

src/material/form-field/form-field.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,11 @@ import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';
3333
import {merge, Subject} from 'rxjs';
3434
import {takeUntil} from 'rxjs/operators';
3535
import {MAT_ERROR, MatError} from './directives/error';
36-
import {MatFormFieldFloatingLabel} from './directives/floating-label';
36+
import {
37+
FLOATING_LABEL_PARENT,
38+
FloatingLabelParent,
39+
MatFormFieldFloatingLabel,
40+
} from './directives/floating-label';
3741
import {MatHint} from './directives/hint';
3842
import {MatLabel} from './directives/label';
3943
import {MatFormFieldLineRipple} from './directives/line-ripple';
@@ -151,10 +155,13 @@ const FLOATING_LABEL_DEFAULT_DOCKED_TRANSFORM = `translateY(-50%)`;
151155
},
152156
encapsulation: ViewEncapsulation.None,
153157
changeDetection: ChangeDetectionStrategy.OnPush,
154-
providers: [{provide: MAT_FORM_FIELD, useExisting: MatFormField}],
158+
providers: [
159+
{provide: MAT_FORM_FIELD, useExisting: MatFormField},
160+
{provide: FLOATING_LABEL_PARENT, useExisting: MatFormField},
161+
],
155162
})
156163
export class MatFormField
157-
implements AfterContentInit, AfterContentChecked, AfterViewInit, OnDestroy
164+
implements FloatingLabelParent, AfterContentInit, AfterContentChecked, AfterViewInit, OnDestroy
158165
{
159166
@ViewChild('textField') _textField: ElementRef<HTMLElement>;
160167
@ViewChild('iconPrefixContainer') _iconPrefixContainer: ElementRef<HTMLElement>;
@@ -532,6 +539,11 @@ export class MatFormField
532539
: 'hint';
533540
}
534541

542+
/** Handle label resize events. */
543+
_handleLabelResized() {
544+
this._refreshOutlineNotchWidth();
545+
}
546+
535547
/** Refreshes the width of the outline-notch, if present. */
536548
_refreshOutlineNotchWidth() {
537549
if (!this._hasOutline() || !this._floatingLabel || !this._shouldLabelFloat()) {

0 commit comments

Comments
 (0)