Angular - 菜单 - 如何从最后一个菜单项切换回第一个菜单项

Angular - menu - how to tab from the last menu item back to the first menu item

WCAG 要求上下文菜单或下拉菜单具有关闭的 Tab 键顺序。因此,在切换到菜单的最后一个菜单项之后,后续的选项卡应该再次 select 第一个菜单项。

我希望下一个解决方案能奏效。在三个菜单项中的第二个中按 Tab 键时,将跳过第三个菜单项,第一个菜单项获得焦点。为什么跳过第三个菜单项?

问题:如何从 1st > 2nd > 3rd > 1st 菜单项每次切换?

尝试 1:第三个/最后一个菜单项的选项卡将立即转到菜单项 1。

<div ngbDropdown class="d-inline-block">
  <button class="btn btn-outline-primary" id="dropdownBasic1" ngbDropdownToggle
          (click)="open($event)">Actions</button>
  <div ngbDropdownMenu aria-labelledby="dropdownBasic1">
    <button #firstbutton (click)="doAction( $event, 'Errors', journalEntry.id)"
            ngbDropdownItem>Errors</button>
    <button (click)="doAction( $event, 'Events', journalEntry.id)"
            ngbDropdownItem>Events</button>
    <button (click)="doAction( $event, 'Counts', journalEntry.id)"
            (keydown.tab)="gotoFirstMenuItem($event)" ngbDropdownItem>Counts</button>
  </div>
</div>

组件:

@ViewChild("firstbutton") firstbutton: ElementRef;

gotoMenuItem(event, nextTabElement: number) {
  event.stopPropagation();
  console.log('tab on last menu item');
  this.firstbutton.nativeElement.focus();
} 

尝试 2:这将始终跳过 1 个选项卡(或插入一个额外的选项卡);

模板:

<div ngbDropdown class="d-inline-block">
  <button class="btn btn-outline-primary" id="dropdownBasic1" ngbDropdownToggle
          (click)="open($event)" (keydown.enter)="open($event)">Actions</button>
  <div ngbDropdownMenu aria-labelledby="dropdownBasic1">
    <button #firstbutton (click)="doAction( $event, 'Errors', journalEntry.id)"
            (keydown.enter)="doAction( $event, 'Errors', journalEntry.id)"
            (keydown.tab)="doNothing($event)"
            (keyup.tab)="gotoMenuItem($event, 2)"
            ngbDropdownItem>Errors</button>
    <button #secondbutton (click)="doAction( $event, 'Events', journalEntry.id)"
            (keydown.enter)="doAction( $event, 'Events', journalEntry.id)"
            (keydown.tab)="doNothing($event)"
            (keyup.tab)="gotoMenuItem($event, 3)"
            ngbDropdownItem>Events</button>
    <button #thirdbutton (click)="doAction( $event, 'Counts', journalEntry.id)"
            (keydown.enter)="doAction( $event, 'Events', journalEntry.id)"
            (keydown.tab)="doNothing($event)"
            (keyup.tab)="gotoMenuItem($event, 1)" ngbDropdownItem>Counts</button>
  </div>
</div>

组件:

@ViewChild("firstbutton") firstbutton: ElementRef;
@ViewChild("secondbutton") secondbutton: ElementRef;
@ViewChild("thirdbutton") thirdbutton: ElementRef;

gotoMenuItem(event, nextTabElement: number) {
  event.stopPropagation();
  console.log('tab on last menu item');
  this.rowAction = 'Tab last menu item, going to first: ' + (++(this.tabCounterLastMenuItem));
  switch (nextTabElement) {
    case 1:
      this.firstbutton.nativeElement.focus();
      break;
    case 2:
      this.secondbutton.nativeElement.focus();
      break;
    case 3:
      this.thirdbutton.nativeElement.focus();
      break;
  }
}

我已经尝试在 Stackblitz 上运行这个

https://stackblitz.com/edit/angular-4t9syy?file=src/app/app.component.ts

我必须承认,它的行为与您描述的略有不同,也许我没有正确重现它,即在第一个示例中,它首先跳转到第一个选项卡,然后移动到第二个选项卡,因此转到 3-> 2,我想在你的情况下它在关注第三项之前拦截了事件,看起来好像

e.stopPropagation();

不会阻止默认浏览器行为,我尝试将其更改为

e.preventDefault();

它似乎适用于第一个示例,至少在 Stackblitz 中是这样