除了appendTo="body"之外,如何避免p-dropdown在正文滚动时关闭

问题描述 投票:0回答:4

我在我的项目中使用 Angular 版本 12 和 PrimeNG 版本 12。同样,我使用 primeng 下拉菜单,该下拉菜单在滚动主体时关闭。使用appendTo =“body”不会关闭滚动下拉菜单,而是会随之移动下拉面板。很多人都遇到过这个问题,但我还没有找到任何解决方法。

<div class="customScroll">
  <p-dropdown
    filter="true"
    [options]="options" 
    [(ngModel)]="model" 
    (onChange)="filterTable()"
    [style]="{'width': '100%', 'margin-top': '10px', 'font-family': 'Roboto Regular'}"
  >
  </p-dropdown>
</div>
javascript html angular typescript primeng
4个回答
4
投票

您可以通过传递

overlayOptions

来修补此问题
[overlayOptions]="getOverlayOptions()"

定义为:

getOverlayOptions(): OverlayOptions {
    return {
      listener: (event: Event, options?: OverlayListenerOptions) => {
        return false;
      }
    };
}

如果有人关心这个补丁背后的故事:
您会注意到,在他们的网站上测试他们的组件时,这种情况不会发生,我高度怀疑有人正在阻止滚动事件传播以隐藏错误,因为当我克隆他们的项目并在他们自己的项目内创建一个带有滚动条的新容器时,也会发生同样的意外行为。
无论如何,经过进一步的源代码检查,您会发现一行有关于滚动侦听器的奇怪行,例如:

x || y 

两者都有副作用,只有当第一个返回值被评估为 false 时才会执行第二个。我没有时间给出确切的文件和行号,因为解决这个问题是一个相当漫长的过程。


1
投票

您需要使用PrimeNG下拉列表的

appendTo="body"
属性


0
投票

我对此做了很多研究,但没有发现任何东西。

但是这个问题在最新版本的 ngPrime 14.0.0 中得到了修复


0
投票

您可以像下面这样做,我使用 QueryList 和 ViewChildren 访问所有实例,如果想访问单个实例,您也可以使用 ViewChild。比我重写了滚动或文档调整大小时隐藏下拉菜单的逻辑

Primeng 版本 14

/**
     * *Modifies the behavior of PrimeNG Dropdown components, enhancing their functionality
     * *Adjusts dropdown overlay positioning during scrolling and realignment on window resize
     *
     * @param instances -A QueryList of Dropdown instances to apply the behavior modifications
     */
    public overridePrimeNgDropdownBehavior(instances: QueryList<Dropdown>): void {
        if (instances.length > 0) {
            instances.forEach((instance) => {
                //Aligns the drodpown position on window resize
                instance.onWindowResize = function () {
                    if (instance.overlayVisible && !DomHandler.isTouchDevice()) {
                        instance.show();
                        instance.alignOverlay();
                    }
                };

                //Aligns the dropdown on scroll
                if (!instance.scrollHandler) {
                    instance.scrollHandler = new ConnectedOverlayScrollHandler(
                        instance.containerViewChild.nativeElement,
                        () => {
                            if (instance.overlayVisible) {
                                instance.alignOverlay();
                            }
                        }
                    );
                }

                instance.scrollHandler.bindScrollListener();
            });
        }
    }

Primeng 版本 15 或更高版本

/**
     * *Modifies the behavior of PrimeNG Dropdown components, enhancing their functionality
     * *Adjusts dropdown overlay positioning during scrolling and realignment on window resize
     *
     * @param instances -A QueryList of Dropdown instances to apply the behavior modifications
     */
    public overridePrimeNgDropdownBehavior(instances: QueryList<Dropdown>): void {
        //If there are no instances, return early
        if (!instances.length) return;

        //Define a listener function for Dropdown overlay events
        const dropdownOverlayListener = (
            event: Event,
            options?: OverlayListenerOptions,
            dropdownOverlayPanel?: Nullable<Overlay>
        ): boolean | void => {
            //If options or DropdownOverlayPanel is missing, return early
            if (!options || !options.type || !dropdownOverlayPanel) return;

            //Handle different types of overlay events
            switch (options.type) {
                case 'scroll':
                case 'resize':
                    //Adjust Dropdown overlay positioning during scrolling and resize
                    dropdownOverlayPanel.alignOverlay();
                    break;
                case 'outside':
                    //Hide the Dropdown overlay panel if clicked outside
                    dropdownOverlayPanel.hide();
                    break;
                default:
                    break;
            }
        };

        //Iterate over each Dropdown instance and apply the behavior modifications
        instances.forEach((instance) => {
            //Get the overlay panel associated with the Dropdown
            const dropdownOverlayPanel = instance.overlayViewChild;

            //Set overlay options for the Dropdown
            instance.overlayOptions = {
                mode: 'overlay',
                hideTransitionOptions: '0s',
                showTransitionOptions: '0s',
                listener: (event: Event, options?: OverlayListenerOptions) =>
                    dropdownOverlayListener(event, options, dropdownOverlayPanel)
            };
        });
    }
© www.soinside.com 2019 - 2024. All rights reserved.