components icon indicating copy to clipboard operation
components copied to clipboard

autocomplete does not stick when scrolling

Open weijyewang opened this issue 7 years ago • 47 comments

Bug, feature request, or proposal:

Bug

What is the expected behavior?

The autocomplete drop down list should stick to the bottom of input element when scrolling

What is the current behavior?

The drop down list is sticky to position on the screen, it will not follow the input element position when scrolling

What are the steps to reproduce?

image

What is the use-case or motivation for changing an existing behavior?

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

Windows 10 64 bit Chrome Version 64.0.3282.167 (Official Build) (64-bit) Angular 5.1.2 Angular Material 5.0.2 TypeScript 2.7.1

Is there anything else we should know?

weijyewang avatar Feb 22 '18 03:02 weijyewang

That's because, by default, Material won't listen to scroll events on all elements. Is your main scroll container something different than the body?

crisbeto avatar Feb 22 '18 12:02 crisbeto

@crisbeto yes, the scroll container is actually mat-sidenav-content element, descendant of the body element, which has overflow: auto set into it. Is there a way to configure the event listener to listen to the element of choosing?

weijyewang avatar Feb 22 '18 16:02 weijyewang

Usually you'd have to add the cdkScrollable attribute to your scroll container so the CDK can pick it up, however the sidenav container has it set up already. Can you try adding the ScrollDispatchModule from @angular/cdk/scrolling to your imports?

crisbeto avatar Feb 24 '18 15:02 crisbeto

I have noticed that the mat-select does not have this issue, as it blocks scroll action when the panel is opened.

May be autocomplete should follow the same approach.

karan-kang avatar Apr 20 '18 16:04 karan-kang

Having same use case as @weijyewang with ScrollDispatchModule inported. As @Karankang007 mentioned blocking scroll as mentioned here would be fair enough temporary fix. Tried it with MAT_AUTOCOMPLETE_SCROLL_STRATEGY, no luck.

ezo5 avatar May 17 '18 07:05 ezo5

Having same issue when the main scroll container is content of dialog popup (mat-dialog-content). Ideally it should work similar to mat-select.

NithinBiliya avatar Dec 11 '18 09:12 NithinBiliya

I was with the same problem, I used the workaround described in this issue:

https://github.com/angular/material2/issues/7897

israelpereira avatar Dec 11 '18 13:12 israelpereira

@israelpereira #7897 did help. On using cdkScrollable the dropdown section is sticking to the input, but it is no more contained within the dialog content section.

Reproduced on stackblitz. Click on the 'open popup' button and scroll the dialog section.

I think the ideal solution would be to disable scroll when the dropdown is opened as suggested by @Karankang007 in comment.

NithinBiliya avatar Dec 15 '18 06:12 NithinBiliya

I had the same issue.. to solve it.. I found something called ScrollStrategy and I used the following code:

export function scrollFactory(overlay: Overlay): () => CloseScrollStrategy {
	return () => overlay.scrollStrategies.close();
}

@NgModule({
	imports: [modules],
	exports: [modules],
	providers: [
		{ provide: MAT_AUTOCOMPLETE_SCROLL_STRATEGY, useFactory: scrollFactory, deps: [Overlay] }
	]
})
export class AppModule {}

It closes the autocomplete box when it identifies the scroll outside the autocomplete.

hope it helps.

israelpereira avatar Dec 17 '18 19:12 israelpereira

thanks @israelpereira. this helps. The dropdown overlay closes on scroll. The only side effect is that to open the dropdown overlay once again, the focus has to be taken out of the autocomplete input and back into it.

Behaviour similar to mat-select could be achieved if BlockScrollStrategy worked, but sadly it doesn't.

NithinBiliya avatar Dec 18 '18 11:12 NithinBiliya

Welcome, I had this issue too...

@ViewChild('searchInput', { read: MatAutocompleteTrigger })
triggerAutocompleteInput: MatAutocompleteTrigger;

openAutocompletePanel(){
this.triggerAutocompleteInput.openPanel();
}

//html
<input  (click)="openAutocompletePanel()" />

add this code to the component and put the (click)="openAutocompletePanel()" in the input field, it will solves the problem.

I don't know if it is the best solution, probably not, but worked .. I was losing so much time on it..

israelpereira avatar Dec 18 '18 19:12 israelpereira

@israelpereira thanks for MatAutocompleteTrigger.openPanel() for opening the dropdown section

NithinBiliya avatar Dec 19 '18 14:12 NithinBiliya

Solution:

import { ScrollingModule } from '@angular/cdk/scrolling';

Locate the Modal that has this component. Place the cdkScrollable directive on the outer most div of that Modal... ie:

<div class="full-page-takeover" cdkScrollable> {{ modal content }} </div>

This worked for me.

omaracrystal avatar May 12 '19 19:05 omaracrystal

just add below code to your autocomplete function and it will work

appendTo: $('#tag').parent(),

this will stick the autocomplete list to its parent textbox

YasinK123 avatar Jun 27 '19 08:06 YasinK123

Is there any solution for mat-autocomplete not sticking to the input when scrolled.

Note: None of the given solution worked for me

Prakashpb avatar Jul 24 '19 09:07 Prakashpb

@omaracrystal solution work for me, but then , i have problem with z-index.

image

image

yantrab avatar Aug 27 '19 12:08 yantrab

image i have the same problem

HiagoMM avatar Oct 21 '19 18:10 HiagoMM

I'm having the same issue when I used autocomplete inside mat-side-nav

fzs1994 avatar Dec 24 '19 14:12 fzs1994

Hey @weijyewang, @fzs1994 I'm in the same scenario, did you manage to solve it ? None of the given solution worked for me.

matiasfs12 avatar Jan 28 '20 14:01 matiasfs12

@matiasfs12 I just added cdkScrollable to the parent element just like what @crisbeto and @omaracrystal suggested. I am happy to help if you can provide a stackblitz https://stackblitz.com/edit/angular

weijyewang avatar Jan 28 '20 15:01 weijyewang

@matiasfs12 I just added cdkScrollable to the parent element just like what @crisbeto and @omaracrystal suggested. I am happy to help if you can provide a stackblitz https://stackblitz.com/edit/angular

That doesn't work for me since i'm not using mat-sidenav-container, nor mat-sidenav-content, actually i'm putting the cdkScrollable on mat-sidenav tag, but the scroll listener it's not even firing up because there is an intermediate element mat-drawer-inner-container which actually scroll up/down the content, and i cannot disable the scroll in this element with CSS.

image

In any case, i will try to do a stackblitz, thanks in advance!

matiasfs12 avatar Jan 28 '20 16:01 matiasfs12

@matiasfs12 you just have to set cdkScrollable to the parent container that is scrollable. It can be any elements like div. If mat-sidenav is giving you the problem maybe you can implement a sidenav on your own? This is how I use cdkScrollable in my code

image

weijyewang avatar Jan 29 '20 15:01 weijyewang

Hey @weijyewang , Finally managed to get it working, I had to append a <mat-sidenav-content> into <mat-sidenav>, setting cdkScrollable on it, and some hacky CSS styles, thx mate

matiasfs12 avatar Jan 30 '20 18:01 matiasfs12

All the above solutions not worked for me, Please anyone has the best solution. I have used Angular material 8.2.3 version with Angular 8.

rahulkathar avatar Feb 24 '20 14:02 rahulkathar

The above solution works. you just have to find the class where you are defining the overflow property to scroll this will give you the element which is controlling the scrolling of the page. Then add cdkScrollable to that element. And add this in your module. since ScrollDispatchModule has been renamed to ScrollingModule. import { ScrollingModule } from '@angular/cdk/scrolling';

SurabhiPal0892 avatar Mar 05 '20 12:03 SurabhiPal0892

Nothing worked for me.

panyann avatar Apr 24 '20 10:04 panyann

@panyann If you have a autocomplete within a mat dialog - this is how I solved this issue.

  1. Wrap all your content with <mat-dialog-content></mat-dialog-content>
  2. Place the directive cdkScrollable on that ^
<mat-dialog-content cdkScrollable>...</mat-dialog-content>
  1. In scss target .mat-dialog-content and give it a max-height of 100vh
.mat-dialog-content {
    width: 100%;
    height: 100%;
    max-height: 100vh;
  }

omaracrystal avatar Apr 25 '20 20:04 omaracrystal

@omaracrystal I don't have a dialog and cdkScrollable seems to not work whatever I do! So I made a workaround and I will share with everyone...

First of all we need to be able to use autoComplete methods, so we must take this control from the view. Add the id: #autoCompleteInput

<input
        #autoCompleteInput
        type="text"
        class="form-control"
        matInput
        [matAutocomplete]="auto"
        formControlName="country"
        (input)="filterCountries($event.target.value)"
      />

In the component:

@ViewChild('autoCompleteInput', { read: MatAutocompleteTrigger })
  autoComplete: MatAutocompleteTrigger;

Now we have autoComplete as a variable. Next we need a scrolling event:

ngOnInit(): void {
    window.addEventListener('scroll', this.scrollEvent, true);
}

And finally add a function to the component:

scrollEvent = (event: any): void => {
    if(this.autoComplete.panelOpen)
      // this.autoComplete.closePanel();
      this.autoComplete.updatePosition();
};

You can set it to close the panel or update its position. Problem solved, but is not perfect if you have a lot of these autoComplete elements.

I can only wonder why this position update does not happen automatically and we all need to make idiots out of ourselves and waste time for finding solution...

panyann avatar Apr 27 '20 10:04 panyann

Yes this solved the problem. Thank you @panyann

fahmadliquid avatar May 07 '20 12:05 fahmadliquid

Thank you @panyann

This is exactly what I wanted

Rakshithkakathkar avatar May 08 '20 06:05 Rakshithkakathkar