components icon indicating copy to clipboard operation
components copied to clipboard

bug(autocomplete): scroll locking

Open RobinKamps opened this issue 3 years ago • 5 comments

Is this a regression?

  • [ ] Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was

No response

Description

autocomplete does not behave like other material compnents like menu or select - those lock the scrolling of the underlying div/html/body.

autocomplete

Reproduction

Steps to reproduce:

  1. https://material.angular.io/components/select/overview
  2. open autocomplete and scroll on body

Expected Behavior

scroll is locked

Actual Behavior

scrolling is enabled - inconvenient behavior between material components, resulting in multiple issues e.g. z-index or if a container for scrolling is used the autocomplete panel does not scroll.

Environment

  • Angular: 15.1.1
  • CDK/Material: 15.1.1
  • Browser(s): all
  • Operating System (e.g. Windows, macOS, Ubuntu): all

RobinKamps avatar Jan 24 '23 20:01 RobinKamps

Is this under any considerations for fixing? This is also not working when having more than one autocompletes per page and using scroll blocking strategy. Focusing first autocomplete will work as expected, but if you focus first, and then focus second, the second one scroll strategy is broken. Oh, it may be a different issue after all. Just notice that everywhere on material demo page blocking scroll strategy is working, but not for autocomplete.

MardariG avatar Jun 07 '24 09:06 MardariG

Any way to bypass or patch this problem via CSS or using another API for the popover? (in case is using some specific API for that purpose). We are using Angular Material 17 and the problem persists (even in AM18).

This doesn't replicate if you use a mouse, it only triggers when using the mousepad.

danieldiazastudillo avatar Jun 18 '24 16:06 danieldiazastudillo

Is it really hard to add a transparent backdrop?

M0o4 avatar Sep 02 '24 11:09 M0o4

Solution for 16.0.2

@Directive({
  selector: '[matAutocomplete][autocompleteBackdrop]',
})
export class MatAutocompleteBackdropDirective implements OnInit {
  constructor(private readonly matAutocompleteTrigger: MatAutocompleteTrigger) {}

  ngOnInit(): void {
    this.matAutocompleteTrigger['_getOverlayConfig'] = (): OverlayConfig => {
      return new OverlayConfig({
        positionStrategy: this.matAutocompleteTrigger['_getOverlayPosition'](),
        scrollStrategy: this.matAutocompleteTrigger['_scrollStrategy'](),
        width: this.matAutocompleteTrigger['_getPanelWidth'](),
        direction: this.matAutocompleteTrigger['_dir'] ?? undefined,
        panelClass: this.matAutocompleteTrigger['_defaults']?.overlayPanelClass,
        hasBackdrop: true,
        backdropClass: 'cdk-overlay-transparent-backdrop',
      });
    };
  }
}

M0o4 avatar Sep 02 '24 11:09 M0o4

EDIT

I figured that my auto-complete dropdown works as expected. The reason it looked strange in my app, is that the autocomplete dropdown is still visible while the input is out of the view. Image

For me this behavior is a bit strange, but it is also apparent in the autocomplete example page. Can someone point me in the correct direction? How can I close the autocomplete panel once the input is scrolled out of view?

Original Comment

I have the same issue in angular 18 in a dialog:

Repro Steps

  1. Create a dialog with content that requires scrolling to see the full content
  2. Add inputs with autocomplete
  3. Scroll down/up in the dialog.

Actual Result

The autocomplete suggestions are not sticking to its corresponding input (just like the video above)

Expected Result

Autocomplete suggestions sticks to the input, also while scrolling.

Debugging

I am quite new to angular and web-development in general. Some of these concepts are still a bit hard to grasp. However, I have tried several suggestions online:

  • Adding a div with cdkScrollable around mat-dialog-content: Same behavior
  • Adding cdkScrollable to mat-dialog-content: The dialog disappears

Environment

  • Angular: 18.0.0
  • Angular Material: 18.0.0
  • OS: Ubuntu 20.04
  • Browsers: Firefox, Chrome

Hlanden avatar Oct 14 '24 13:10 Hlanden

Hi team, any news on this? i saw this ticket was created in 2023...

EM-LilianaIturribarria avatar Oct 25 '24 16:10 EM-LilianaIturribarria

Solution for 19.2.19

import { MatAutocompleteTrigger } from '@angular/material/autocomplete'
import { OverlayConfig } from '@angular/cdk/overlay'
import { Directive, OnInit } from '@angular/core'

@Directive({
	selector: '[matAutocomplete][autocompleteBackdrop]',
	standalone: true,
})
export class MatAutocompleteBackdropDirective implements OnInit {
	constructor(private readonly matAutocompleteTrigger: MatAutocompleteTrigger) {}

	ngOnInit(): void {
		// Override the private _getOverlayConfig method to inject custom backdrop logic
		;(this.matAutocompleteTrigger as any)._getOverlayConfig = (): OverlayConfig => {
			return new OverlayConfig({
				positionStrategy: (this.matAutocompleteTrigger as any)._getOverlayPosition(),
				scrollStrategy: (this.matAutocompleteTrigger as any)._scrollStrategy(),
				width: (this.matAutocompleteTrigger as any)._getPanelWidth(),
				direction: (this.matAutocompleteTrigger as any)._dir ?? undefined,
				panelClass: (this.matAutocompleteTrigger as any)._defaults?.overlayPanelClass,
				hasBackdrop: true,
				backdropClass: 'cdk-overlay-transparent-backdrop',
			})
		}
	}
}

To use your MatAutocompleteBackdropDirective in an Angular 19 app with standalone components, follow these steps:


Apply the Directive in Your Template

Use it like this in your standalone component’s HTML:

<mat-form-field appearance="outline">
  <input
    matInput
    placeholder="Select item"
    [matAutocomplete]="auto"
    autocompleteBackdrop
    [formControl]="myControl" />

  <mat-autocomplete #auto="matAutocomplete">
    <mat-option *ngFor="let option of options" [value]="option">
      {{ option }}
    </mat-option>
  </mat-autocomplete>
</mat-form-field>

✅ The important part is this attribute: autocompleteBackdrop.


✅ 3. Import the Directive in Your Component

In your standalone component, import the directive in the imports array:

import { Component } from '@angular/core';
import { ReactiveFormsModule, FormControl } from '@angular/forms';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatAutocompleteBackdropDirective } from './mat-autocomplete-backdrop.directive';

@Component({
  selector: 'app-autocomplete-with-backdrop',
  standalone: true,
  imports: [
    ReactiveFormsModule,
    MatFormFieldModule,
    MatInputModule,
    MatAutocompleteModule,
    MatAutocompleteBackdropDirective, // <-- import here
  ],
  templateUrl: './autocomplete-with-backdrop.component.html',
})
export class AutocompleteWithBackdropComponent {
  myControl = new FormControl('');
  options = ['One', 'Two', 'Three'];
}

mallajay avatar Jun 26 '25 11:06 mallajay