MDC 菜单 - 当焦点在输入上时保持菜单打开

MDC menu - keep menu open when focus is on input

我正在使用 mdc 网络组件构建自动完成输入。我有一个输入文本字段和一个菜单。你可以看到codesandox here。 我在 focusin 事件上显示菜单,但如果我开始在输入字段中书写,菜单会立即关闭。

const input = new MDCTextField(document.querySelector(".mdc-text-field"));
const menu = new MDCMenu(document.querySelector(".mdc-menu"));

input.listen("focusin", () => (menu.open = true));

我认为这是因为当在菜单外单击时触发菜单默认行为关闭。这里的问题还在于焦点被文本字段中的第一个菜单项占据。有什么方法可以防止这种情况发生,并打开菜单直到焦点在输入字段上丢失?

这里的问题与可访问性有关,这是按顺序发生的事情:

  1. 当您单击输入时,输入正在获取客户端 "focus"。

  2. 这会触发打开菜单的 "focusin" 事件。

  3. 然后,根据accessibility documentation defined here,MDCMenu会自动聚焦第一个菜单项。

要阻止此焦点自动发生,我们可以设置

menu.setDefaultFocusState(DefaultFocusState.NONE);

DefaultFocusState.NONE

Does not change the focus. Set this if you do not want the menu to grab focus on open. (Autocomplete dropdown menu, for example).

要是这么简单就好了,但是现在的问题是,如果MDCMenu在没有焦点的时候自动关闭。

[edit]: this next section is incorrect, the anchor doesn't achor it open just anchor it around an element

为了解决下一个问题,我们将 MDCMenu 锚定到输入元素(必须是本机元素):

menu.setAnchorElement(document.querySelector(".mdc-text-field"));

最后我们需要告诉 MDCMenu 在焦点从输入中取出后关闭:

input.listen("focusout", () => {
  menu.open = false;
});

您可能还可以调整一些其他问题,但我认为这应该会让您接近。有一个代码共享示例,它也使用 MDCMenu 制作“自动完成下拉菜单”,您可以在此处参考:https://gist.dreamtobe.cn/gpulido/4bae80a5be4fd5c7ed61f1f1667da039

这是经过我的更改后的代码,您可以在您的 codesandbox 中使用:

import { MDCTextField } from "@material/textfield";
import { MDCMenu, DefaultFocusState, Corner } from "@material/menu";
import "./styles.scss";

const input = new MDCTextField(document.querySelector(".mdc-text-field"));
const menu = new MDCMenu(document.querySelector(".mdc-menu"));
menu.setDefaultFocusState(DefaultFocusState.NONE);
menu.setAnchorCorner(Corner.BOTTOM_START);
menu.setAnchorElement(input.component);

input.listen("focusin", () => {
  menu.open = true;
});
input.listen("click", () => {
  menu.open = true;
});
input.listen("focusout", () => {
  menu.open = false;
});