Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mat-autocomplete options dropdown does not stick when scrolling

In my Angular app, I'm using the autocomplete feature from Angular Material:

angular material autocomplete

It works fine, except when I scroll the page:

angular material autocomplete scrolling issue

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.

like image 250
Francesco Borzi Avatar asked Feb 25 '20 15:02

Francesco Borzi


3 Answers

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>
like image 93
Francesco Borzi Avatar answered Nov 12 '22 13:11

Francesco Borzi


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

like image 35
Abhishek Kumar Avatar answered Nov 12 '22 11:11

Abhishek Kumar


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" />
like image 3
Janith Widarshana Avatar answered Nov 12 '22 13:11

Janith Widarshana