NG-ZORRO / ng-zorro-antd

Angular UI Component Library based on Ant Design
https://ng.ant.design
MIT License
8.85k stars 3.9k forks source link

nz-select dropdown content does not scroll with the modal parent #7865

Open maidmehic opened 1 year ago

maidmehic commented 1 year ago

Reproduction link

https://stackblitz.com/edit/angular-a5kqqf?file=src%2Fapp%2Fapp.component.ts

Steps to reproduce

Open the modal. Click the nz-select control. Scroll the modal content.

What is expected?

nz-select dropdown content should scroll together with the rest of the page and follow the control.

There are many tickets regarding this on ant-design repo. Please take a look: https://github.com/ant-design/ant-design/issues/8268

What is actually happening?

nz-select dropdown content does not move with the rest of the page and is fixed in one position.

Screenshot 2023-03-08 at 11 51 07

Environment Info
ng-zorro-antd 15.0.2
Browser Chrome
Galiza commented 1 year ago

This also happens on the newer version.

ng-zorro-antd 15.0.3
felipesantos1504 commented 1 year ago

this happens to me aswell but with the nz-mention, but in the demo docs it does work

vhphuc commented 1 year ago

this issue only occur when use in nz-modal.

danilmoro3 commented 1 year ago

The same for DatePicker, TreeSelect, Popover, etc. Reproduces in Drawer component as well.

@vthinkxie Can you please tell when the fix is expected?

ttakennn commented 1 year ago

hi @vthinkxie I got the same issue. Please help to fix this issue.

DownAndDoerrty commented 1 year ago

@vthinkxie, I'm also having the same issue

alexmao1024 commented 9 months ago

I also have the same issue, and there are many dropdown menus in my project that exist on a scrollable page. This is a significant issue for me. Has anyone fixed it yet?

majid-seifi commented 9 months ago

I also have the same issue! Has anyone any solution?

saikrishnasandiri commented 8 months ago

Iam also having same issue

is-tongben commented 6 months ago

Listen for box scrolling events, trigger the 'updateCdkConnectedOverlayPositions' method of the' NzSelectComponent ' instance element image

Guruprasanth98 commented 4 months ago

Iam also having same issue. please help me someone

barryross commented 3 months ago

Having same issue, any update?

mehdiboutoumit commented 2 months ago

Same issue.

andressalhenriques commented 1 month ago

Hi. Someone find a solution ?

nainiteknol123 commented 1 month ago

Is there any solution for this ?

Lukinoh commented 1 month ago

As a workaround, you can write a custom ScrollDispatcher. The ScrollDispatcher is used to emit an event when any one of the Scrollable references emit a scrolled event. It is used to update the position of an overlay when a scroll occurs, and by default, it listens only to the document.defaultView.window.

So I wrote the following CustomScrollDispatcher that will listen to all scroll events in your page, and register the HTMLElement who was scrolled in the ScrollDispatcher. Hence, when you scroll it, the dropdown position will be updated.

Code is provided as is, I didn't notice yet any side effects.

import {
  ClassProvider,
  ElementRef,
  Inject,
  Injectable,
  NgZone,
  Optional,
} from "@angular/core";
import {CdkScrollable, ScrollDispatcher} from "@angular/cdk/overlay";
import {Platform} from '@angular/cdk/platform';
import {DOCUMENT} from "@angular/common";

@Injectable({providedIn: 'root'})
class CustomScrollDispatcher extends ScrollDispatcher {

  private scrollables: Map<HTMLElement, CdkScrollable> = new Map();

  constructor(_ngZone: NgZone,
              _platform: Platform,
              @Optional() @Inject(DOCUMENT) document: any) {
    super(_ngZone, _platform, document);
    this.registerAllScrollsAsScrollables(document, _ngZone);
  }

  registerAllScrollsAsScrollables(document: Document, ngZone: NgZone) {
    document.addEventListener('scroll', (event) => {
      if (event.target instanceof HTMLElement) {
        if (!this.scrollables.has(event.target)) {
          // Avoid memory leaks
          this.cleanScrollables();

          const scrollable = new CdkScrollable(new ElementRef(event.target), this, ngZone);
          this.scrollables.set(event.target, scrollable);
          this.register(scrollable)
        }
      }
    }, true)
  }

  cleanScrollables(): void {
    for (const [element, scrollable] of this.scrollables) {
      if (!element.isConnected) {
        this.scrollables.delete(element);
        this.deregister(scrollable);
      }
    }
  }

  override ngOnDestroy() {
    super.ngOnDestroy();
    this.scrollables.clear();
  }
}

export const CustomScrollDispatcherProvider: ClassProvider = {
  provide: ScrollDispatcher,
  useClass: CustomScrollDispatcher,
};

// export const appConfig: ApplicationConfig = {
//   providers: [CustomScrollDispatcherProvider, ...]
// };
StefaniOSApps commented 1 month ago

same