Reputation: 61724
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.
Upvotes: 13
Views: 18312
Reputation: 3483
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" />
Upvotes: 4
Reputation: 1040
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
Upvotes: 9
Reputation: 1
My mat-autocomplete is located in mat-dialog, importing ScrollingModule and adding cdkScrollable to my div, didn't seem to help, so I managed to hide the list when scrolling, because when scrolling the list of options isn't really important.
I used:
removeAutocompleteFocus() {
let element = this.document.querySelector('.mat-autocomplete-panel');
if (element) {
element.parentNode.removeChild(element);
}
}
<div (scroll)="removeAutocompleteFocus()"></div>
Upvotes: 0
Reputation: 61724
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>
Upvotes: 19