当使用回车键打开新的 NgbDropdown 时,如何关闭之前打开的 NgbDropdown?

How would one close previously opened NgbDropdowns when new NgbDropdowns are opend using the enter key?

我是 NgbDropdown 和相关 ng-bootstrap 代码的新手,我无法弄清楚如何在使用回车键打开新的 NgbDropdowns 时关闭所有以前的 NgbDropdowns。

我在我的 Angular 项目的一个页面上创建了一些 NgbDropdowns,我发现当我从下拉按钮单击到下拉按钮时,之前打开的下拉菜单关闭;但是,如果我从一个打开的下拉菜单 TAB 到另一个下拉按钮并使用回车键打开第二个下拉菜单(可能需要辅助功能),第一个下拉菜单不会关闭。我留下了两个相互重叠的下拉菜单。

可以在 https://ng-bootstrap.github.io/#/components/dropdown/examples 的 NgbDropdown 主示例页面上复制此序列:在不同的按钮上(顶部的第一个示例。)

序列: 1. Tab 到 "Toggle Dropdown" 2. 按回车键打开下拉菜单 3. Tab 浏览下拉选项,再加一次,这样你就 标签到 "toggle drop-up" 按钮。 4.按回车键 5. 两个下拉菜单将同时打开。

Screen Shot

很明显,当在不同的按钮上按下回车键时,关闭先前点击下拉菜单的代码不起作用。没有找到太多关于打字稿中各种 Ngb 对象可以做什么的文档,我不知道如何在使用回车键打开新下拉菜单时关闭所有以前的下拉菜单。我能想到的就是:

1) 遍历 ts 文件中的所有下拉菜单,在打开最新的之前关闭它们。如果这是最好的解决方案,我看不出有任何方法可以遍历一组打开的下拉菜单。作为 NgbSolution 的一部分,是否有这样的 object/array 可供我使用,或者我是否必须自己将每个添加到数组中?

2) 当在按钮上按下回车键时触发点击事件。同样,我不知道如何让一个事件在 NgbDropdown 对象上触发另一个事件。

如有任何指点,我们将不胜感激。我没有在这里发布我的代码,因为它与上面引用的基本示例相同。

对于您的建议#1(遍历所有下拉菜单并关闭它们),您可以按如下方式实施:

  1. 在您的 HTML 中,使用 Template Reference Variables# 语法)将每个下拉列表声明为 DOM 变量:
    <div ngbDropdown class="d-inline-block" #dd1="ngbDropdown">
    ...
    </div>
  1. click 处理程序添加到 button,如下所示。这允许您将对下拉列表的引用传递给单击处理程序调用的函数:
     <button class="btn btn-outline-primary" id="dropdownBasic1" ngbDropdownToggle (click)="closeOthers(dd1)">Toggle dropdown</button>

下拉列表的完整 HTML 应如下所示:

<div ngbDropdown class="d-inline-block" #dd1="ngbDropdown">
    <button class="btn btn-outline-primary" id="dropdownBasic1" ngbDropdownToggle (click)="closeOthers(dd1)">
        Toggle dropdown
    </button>
    <div ngbDropdownMenu aria-labelledby="dropdownBasic1">
        <button ngbDropdownItem>Action - 1</button>
        <button ngbDropdownItem>Another Action</button>
        <button ngbDropdownItem>Something else is here</button>
    </div>
</div>
  1. 将以下内容添加为 Typescript 组件的 class 变量。这允许您从 Typescript 文件中引用组件中显示的所有下拉菜单:
@ViewChildren(NgbDropdown) dropdowns: QueryList<NgbDropdown>;
  1. 向您的 Typescript 组件添加一个 click 函数:
  closeOthers(clickedDropdown: NgbDropdown) {
    // Close all dropdowns
    this.dropdowns.toArray().forEach(el => {
        el.close();
    });
    // Open the dropdown that was clicked on
    clickedDropdown.open();
  }

现在,无论何时单击下拉菜单(或通过按 Tab 键并按 return select),它都会调用 closeOthers 函数,该函数将:

  • 关闭所有下拉菜单
  • 打开被点击的下拉菜单

请参阅 this StackBlitz 的工作演示。

@Dordrecht - 对于您在下面的评论中提到的功能,我将采用的方法是创建如下服务:

export class ModalNotificationService {

    private _closeModals: Subject<void> = new Subject<void>();
    private _closeModals$: Observable<void> = this._closeModals.asObservable();

    public emitCloseModalEvent() {
        this._closeModals.next();
    }

    get closeModals$(): Observable<void> {
        return this._closeModals$;
    }

}

此服务将被注入到任何具有模态的组件中,并且这些组件将订阅可观察的 closeModals$,然后关闭它们自己组件中的模态。修改 closeOthers 方法以调用新服务的 emitCloseModalEvent 方法来通知所有其他组件。