francium
francium

Reputation: 2480

Angular Material autocomplete panel does not become hidden when autocomplete becomes hidden in scrolling area

enter image description here

There is a bug I've opened up for this (https://github.com/angular/components/issues/20209), I'm asking this question to see if there is a workaround or fix anyone knows.

The issue is visible on this demo page https://stackblitz.com/edit/angular-rczreu

The issue is due to the CDK panel (autocomplete's panel) being rendered as a separate layer in the demo, distinct from the autocomplete element. So when the autocomplete element moves out of the visible area of the scrollable element, the autocomplete does become hidden, but the panel does not due to this separate layer rendering.

In pseudo code, the angular html is as follows,

<html>
<body>
<my-app>

<my-component cdkScrollable> // this is a scrollable element, it's children should become hidden when we scroll

<autocomplete></autocomplete>
<some-other-child></some-other-child>

</my-component>

</my-app>

<div class="cdk-overlay-container">
  // ... other stuff

  <div>
    // autocomplete's panel 
  </div>
</div>

Upvotes: 0

Views: 1341

Answers (1)

Raven
Raven

Reputation: 2257

Okay, I've made a fork of your StackBlitz with the solution here: https://stackblitz.com/edit/angular-rczreu-yqyphm

Basically here are the highlights:

On your component html, I added a component ID to the formField:

<mat-form-field #formField class="example-full-width">

Then on your component ts, I added the references to the ViewChild for the Autocomplete elements (the form field and the Autocomplete panel itself):

@ViewChild(MatAutocompleteTrigger) autocomplete: MatAutocompleteTrigger;
@ViewChild("formField") autoCompleteFormField: MatFormField;

Then I added an implementation of AfterViewInit to your component to make sure the view elements are already loaded so that it is not undefined.

ngAfterViewInit() {
    var observer = new IntersectionObserver((entries) => {
      if(!entries[0].isIntersecting)
        console.log('Element is is not in screen');
        this.autocomplete.closePanel();
    }, { threshold: [1] });

    
 observer.observe(this.autoCompleteFormField._elementRef.nativeElement);
}

So what this code snippet do is using the efficient Intersection Observer API which detects if an element is on screen or not. Then just simply close the autocomplete panel if the element is off-screen.

https://usefulangle.com/post/113/javascript-detecting-element-visible-during-scroll#:~:text=To%20know%20whether%20the%20element%20is%20fully%20visible%20in%20viewport,height%20and%20bottom%20%3E%3D%200.

Upvotes: 1

Related Questions