From fbc22e1d5baa9437107d97d5d955206933bbae6e Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Mon, 21 Sep 2026 12:38:55 +0200 Subject: [PATCH] fix(cdk/overlay): replace getAttachedOverlays with signal Replaces the `getAttachedOverlays` API with a signal. --- goldens/cdk/overlay/index.api.md | 6 +++--- src/cdk/overlay/overlay-ref.ts | 16 ++++++++-------- src/cdk/overlay/overlay.spec.ts | 14 +++++++------- src/cdk/overlay/public-api.ts | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/goldens/cdk/overlay/index.api.md b/goldens/cdk/overlay/index.api.md index bbceb42fd9bd..e7f2bcb0007f 100644 --- a/goldens/cdk/overlay/index.api.md +++ b/goldens/cdk/overlay/index.api.md @@ -32,6 +32,9 @@ import { TrackByFunction } from '@angular/core'; import { Type } from '@angular/core'; import { ViewContainerRef } from '@angular/core'; +// @public +export const attachedOverlays: i0.Signal; + // @public export class BlockScrollStrategy implements ScrollStrategy { constructor(_viewportRuler: ViewportRuler, document: any); @@ -332,9 +335,6 @@ export class FullscreenOverlayContainer extends OverlayContainer implements OnDe static ɵprov: i0.ɵɵInjectableDeclaration; } -// @public -export function getAttachedOverlays(): OverlayRef[]; - // @public export class GlobalPositionStrategy implements PositionStrategy { apply(): void; diff --git a/src/cdk/overlay/overlay-ref.ts b/src/cdk/overlay/overlay-ref.ts index f88b3ce97233..631c1192fa49 100644 --- a/src/cdk/overlay/overlay-ref.ts +++ b/src/cdk/overlay/overlay-ref.ts @@ -15,6 +15,7 @@ import { NgZone, Renderer2, afterNextRender, + signal, } from '@angular/core'; import {Observable, Subject, Subscription, SubscriptionLike} from 'rxjs'; import {Direction, Directionality} from '../bidi'; @@ -37,12 +38,10 @@ export function isElement(value: any): value is Element { return value && (value as Element).nodeType === 1; } -const attachedOverlays = new Set(); +const attachedOverlaysInternal = signal([]); -/** Gets all overlays that are currently attached. */ -export function getAttachedOverlays(): OverlayRef[] { - return Array.from(attachedOverlays); -} +/** Signal with all of the overlays that are currently attached. */ +export const attachedOverlays = attachedOverlaysInternal.asReadonly(); /** * Reference to an overlay that has been created with the Overlay service. @@ -149,7 +148,8 @@ export class OverlayRef implements PortalOutlet { this._updateStackingOrder(); this._updateElementSize(); this._updateElementDirection(); - attachedOverlays.add(this); + + attachedOverlaysInternal.update(value => (value.includes(this) ? value : [...value, this])); if (this._scrollStrategy) { this._scrollStrategy.enable(); @@ -256,7 +256,7 @@ export class OverlayRef implements PortalOutlet { this._detachContentWhenEmpty(); this._locationChanges.unsubscribe(); this._outsideClickDispatcher.remove(this); - attachedOverlays.delete(this); + attachedOverlaysInternal.update(value => value.filter(current => current !== this)); return detachmentResult; } @@ -293,7 +293,7 @@ export class OverlayRef implements PortalOutlet { this._detachments.complete(); this._completeDetachContent(); this._disposed = true; - attachedOverlays.delete(this); + attachedOverlaysInternal.update(value => value.filter(current => current !== this)); } /** Whether the overlay has attached content. */ diff --git a/src/cdk/overlay/overlay.spec.ts b/src/cdk/overlay/overlay.spec.ts index 43b1a1936909..5b18b69335f6 100644 --- a/src/cdk/overlay/overlay.spec.ts +++ b/src/cdk/overlay/overlay.spec.ts @@ -29,7 +29,7 @@ import { PositionStrategy, ScrollStrategy, createOverlayRef, - getAttachedOverlays, + attachedOverlays, } from './index'; describe('Overlay', () => { @@ -481,24 +481,24 @@ describe('Overlay', () => { it('should track when an overlay is attached and detached', () => { const overlayRef = createOverlayRef(injector); - expect(getAttachedOverlays()).toEqual([]); + expect(attachedOverlays()).toEqual([]); overlayRef.attach(componentPortal); - expect(getAttachedOverlays()).toEqual([overlayRef]); + expect(attachedOverlays()).toEqual([overlayRef]); overlayRef.detach(); - expect(getAttachedOverlays()).toEqual([]); + expect(attachedOverlays()).toEqual([]); }); it('should track when an overlay is attached and disposed', () => { const overlayRef = createOverlayRef(injector); - expect(getAttachedOverlays()).toEqual([]); + expect(attachedOverlays()).toEqual([]); overlayRef.attach(componentPortal); - expect(getAttachedOverlays()).toEqual([overlayRef]); + expect(attachedOverlays()).toEqual([overlayRef]); overlayRef.dispose(); - expect(getAttachedOverlays()).toEqual([]); + expect(attachedOverlays()).toEqual([]); }); describe('positioning', () => { diff --git a/src/cdk/overlay/public-api.ts b/src/cdk/overlay/public-api.ts index edc718feff06..bf2fd93d1fb2 100644 --- a/src/cdk/overlay/public-api.ts +++ b/src/cdk/overlay/public-api.ts @@ -20,7 +20,7 @@ export { CDK_CONNECTED_OVERLAY_DEFAULT_CONFIG, } from './overlay-directives'; export {FullscreenOverlayContainer} from './fullscreen-overlay-container'; -export {OverlayRef, OverlaySizeConfig, getAttachedOverlays} from './overlay-ref'; +export {OverlayRef, OverlaySizeConfig, attachedOverlays} from './overlay-ref'; export {ViewportRuler} from '../scrolling'; export {ComponentType} from '../portal'; export {OverlayPositionBuilder} from './position/overlay-position-builder';