In my Angular app, I'm using the autocomplete feature from Angular Material:
It works fine, except when I scroll the page:
Basically the dropdown does not stick in its position when scrolling and I can't figure out why.
In the official Material documentation page, it works well by automatically updating the top
and left
properties of the element. However, this does not happen in my app.
After doing some research, I've found a solution posted by omaracrystal on github.
What I needed to do is to:
1) Import the ScrollingModule
of the Angular CDK
import { ScrollingModule } from '@angular/cdk/scrolling';
@NgModule({
imports: [
// ...
ScrollingModule,
],
// ...
})
export class MyAppModule { }
2) Find the outermost div that contains my autocomplete input and apply the cdkScrollable
directive:
<div cdkScrollable>
<!-- the autocomplete is located somewhere here, not necessarily as direct child -->
</div>
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();
};
Ref: Origin
Following solution works for me. Hope this will be a help to someone.
I added AutocompletePositionModule module. Then added directive and used in many places in my project.
Module file
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AutocompletePositionDirective } from './autocomplete-position.directive';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
@NgModule({
declarations: [
AutocompletePositionDirective
],
exports: [
AutocompletePositionDirective
],
imports: [
CommonModule,
MatAutocompleteModule,
]
})
export class AutocompletePositionModule { }
Directive file
import { Directive, Input, OnDestroy } from '@angular/core';
import { MatAutocompleteTrigger } from '@angular/material/autocomplete';
@Directive({
selector: '[appAutocompletePosition]',
exportAs : 'appAutocompletePosition'
})
export class AutocompletePositionDirective implements OnDestroy {
public constructor(
private readonly matAutocompleteTrigger: MatAutocompleteTrigger,
) {
window.addEventListener('scroll', this.scrollEvent, true);
}
public ngOnDestroy(): void {
window.removeEventListener('scroll', this.scrollEvent, true);
}
private scrollEvent = (): void => {
if (this.matAutocompleteTrigger == null) {
return;
}
if (this.matAutocompleteTrigger.panelOpen) {
this.matAutocompleteTrigger.updatePosition();
}
}
}
Usage
<input type="text" matInput [matAutocomplete]="auto" #trigger="matAutocompleteTrigger" appAutocompletePosition="trigger" />
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With