From 008212a9807fd01fd32fe136a075763b7b2c854d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joy=20Serqui=C3=B1a?= <44146839+essjay05@users.noreply.github.com> Date: Thu, 13 Jun 2024 09:45:29 -0700 Subject: [PATCH] fix(material/autocomplete): autocomplete panel top is cut off in landscape mode (#28982) * fix(material/autocomplete): autocomplete panel top is cut off in landscape mode Fixes a bug in the Angular Material Autocomplete component where the autocomplete panel listbox top is cut off by the device screen when being viewed in landscape mode. This is because the listbox max-height is greater than the distance between the top of the autocomplete input and the screen top. Fixes b/284148377 * fix(material/autocomplete): autocomplete panel top is cut off in landscape mode Fixes lint error from previous commit which fixes Angular Component's autocomplete panel top from being cut off when viewed in landscape mode. The previous max-height of the panel is more than the height of the panel from the top of the input when in the bottom half to the top of the device's screen. Fixes b/284148377 * fix(material/autocomplete): autocomplete panel top cut off in landscape mode Fixes a bug in the Angular Material Autocomplete component where the autocomplete panel listbox is cut off by the device screen when being viewed in landscape mode. This is because the CDK overlay does not adjust its size based on the screen constraints when triggered. Fixes b/284148377 * fix(material/autocomplete): autocomplete panel top cut off in mobile landscape mode Fixes a bug in the Angular Material Autocomplete component where the autocomplete panel top was being cut off by the screen in mobile landscape mode. Updates previous fix to target adjustments on HandsetLandscape only. Fixes b/284148377 * refactor(material/autocomplete): autocomplete panel top cut off in mobile landscape mode Removing unnecessary comments. Fixes: b/284148377 * refactor(material/autocomplete): Injects Breakpoint to fix breaking tests Fixes broken presubmit tests for Angular Component's Autocomplete constructor by injecting BreakpointObserver rather than adding to the constructor. Fixes b/247881646 * fix(material/autocomplete): update style.bottom value for broken test Fixes breaking Angular Component Autocomplete comoponent's autocomplete spec.ts so that the value falls within an acceptable range based on the new behavior of the autocomplete in landscape mode. Fixes b/284148377 * fix(material/autocomplete): panel top gets cut off in mobile landscape view Updates previous fix to unsubscribe from the _breakpointObserver on ngOnDestroy. Fixes b/284148377 * fix(material/autocomplete): autocomplete panel gets cut off in mobile landscape Updates fix to autocomplete panel which was getting cut off in mobile landscape by correctly assigning const isHandsetLandscape to the subscription result.matches value and thus if isHandsetLandscape is true then applying flexible dimensions, grow after open and with viewport margin to the panel on open. Fixes b/284148377 * fix(material/autocomplete): autocomplete panel top cut off in mobile landscape Fixes Angular Components autocomplete so that when the panel is open in mobile landscape that it does not cut off at the top and the panel resizes/adjusts according to the viewport. Updates the previous fix to avoid subscribing to handsetLandscapeSubscription as a side effect. Fixes b/284148377 * fix(material/autocomplete): resets autocomplete panel positionStrategy when not in mobile landscape Updates the previous fix which checks for Breakpoint.HandsetLandscape and applies flexibleDimensions withGrowAfterOpen and adds withViewportMargin and removes those values if Breakpoint.HandsetLandscape is false. Fixes b/284148377 * refactor(material/autocomplete): autocomplete panel cut off in mobile landscape Updates BreakpointObserver import after rebasing latest changes. Fixes b/284148377 --- .../autocomplete/autocomplete-trigger.ts | 27 +++++++++++++++++++ .../autocomplete/autocomplete.spec.ts | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/material/autocomplete/autocomplete-trigger.ts b/src/material/autocomplete/autocomplete-trigger.ts index bbfb7756f71f..45211bb28e19 100644 --- a/src/material/autocomplete/autocomplete-trigger.ts +++ b/src/material/autocomplete/autocomplete-trigger.ts @@ -9,6 +9,7 @@ import {addAriaReferencedId, removeAriaReferencedId} from '@angular/cdk/a11y'; import {Directionality} from '@angular/cdk/bidi'; import {DOWN_ARROW, ENTER, ESCAPE, TAB, UP_ARROW, hasModifierKey} from '@angular/cdk/keycodes'; +import {BreakpointObserver, Breakpoints} from '@angular/cdk/layout'; import { ConnectedPosition, FlexibleConnectedPositionStrategy, @@ -161,6 +162,10 @@ export class MatAutocompleteTrigger /** Subscription to viewport size changes. */ private _viewportSubscription = Subscription.EMPTY; + /** Implements BreakpointObserver to be used to detect handset landscape */ + private _breakpointObserver = inject(BreakpointObserver); + private _handsetLandscapeSubscription = Subscription.EMPTY; + /** * Whether the autocomplete can open the next time it is focused. Used to prevent a focused, * closed autocomplete from being reopened if the user switches to another browser tab and then @@ -282,6 +287,7 @@ export class MatAutocompleteTrigger window.removeEventListener('blur', this._windowBlurHandler); } + this._handsetLandscapeSubscription.unsubscribe(); this._viewportSubscription.unsubscribe(); this._componentDestroyed = true; this._destroyPanel(); @@ -790,6 +796,26 @@ export class MatAutocompleteTrigger overlayRef.updateSize({width: this._getPanelWidth()}); } }); + // Subscribe to the breakpoint events stream to detect when screen is in + // handsetLandscape. + this._handsetLandscapeSubscription = this._breakpointObserver + .observe(Breakpoints.HandsetLandscape) + .subscribe(result => { + const isHandsetLandscape = result.matches; + // Check if result.matches Breakpoints.HandsetLandscape. Apply HandsetLandscape + // settings to prevent overlay cutoff in that breakpoint. Fixes b/284148377 + if (isHandsetLandscape) { + this._positionStrategy + .withFlexibleDimensions(true) + .withGrowAfterOpen(true) + .withViewportMargin(8); + } else { + this._positionStrategy + .withFlexibleDimensions(false) + .withGrowAfterOpen(false) + .withViewportMargin(0); + } + }); } else { // Update the trigger, panel width and direction, in case anything has changed. this._positionStrategy.setOrigin(this._getConnectedElement()); @@ -881,6 +907,7 @@ export class MatAutocompleteTrigger } private _getOverlayPosition(): PositionStrategy { + // Set default Overlay Position const strategy = this._overlay .position() .flexibleConnectedTo(this._getConnectedElement()) diff --git a/src/material/autocomplete/autocomplete.spec.ts b/src/material/autocomplete/autocomplete.spec.ts index e3fb456880b0..cee2f191382b 100644 --- a/src/material/autocomplete/autocomplete.spec.ts +++ b/src/material/autocomplete/autocomplete.spec.ts @@ -2183,7 +2183,7 @@ describe('MDC-based MatAutocomplete', () => { let inputReference = fixture.debugElement.query(By.css('.mdc-text-field'))!.nativeElement; // Push the element down so it has a little bit of space, but not enough to render. - inputReference.style.bottom = '75px'; + inputReference.style.bottom = '100px'; inputReference.style.position = 'fixed'; dispatchFakeEvent(inputEl, 'focusin');