保持ng-content的所有焦点功能

问题描述

Angular 9和Angular材质

我将mat-chip-list包装在foo-chip-list元素中。但是,我失去了箭头功能转到下一个芯片的a11y功能。无论如何,是否需要保留该功能而不必重新编码mat-chip-list中已经编码的内容

此外,我可以通过cdk门户而不是ng-content来传递芯片元素并仍然保留原始的芯片列表等箭头功能吗?

foo-chip-list元素:

<mat-chip-list
    [aria-orientation]= "ariaOrientation"
    [multiple]="multiple"
    [selectable]="selectable"
    class="atlas-chip-list"
    [ngClass]="{'mat-chip-list-stacked' : ariaOrientation == 'vertical'}">

  <ng-content></ng-content>

</mat-chip-list>

解决方法

我设法做到了,但是您需要使用@HostListener,这可能会影响应用程序的其他部分。

在您的FooChipListComponent中,添加以下内容:

@ContentChildren(MatChip,{ descendants: true }) chips: QueryList<MatChip>;

_keyManager: FocusKeyManager<MatChip>;

@HostListener('keydown',['$event'])
keydown(event: any) {
  this._keyManager.onKeydown(event);
}

ngAfterContentInit() {
  this._keyManager = new FocusKeyManager<MatChip>(this.chips)
    .withWrap()
    .withVerticalOrientation()
    .withHomeAndEnd()
    .withHorizontalOrientation('ltr');
}

在将FocusKeyManager元素替换为筹码之后,使用Material的a11y中的<ng-content>在筹码上设置键盘焦点/导航。 @ContentChildren负责获取筹码-我们需要使用<ng-content>而不是ViewChildren,而是使用ContentChildren。

keydown方法将keydown事件传递给FocusKeyManager,当您按下方向箭头键时,它将负责导航。

我制作了working StackBlitz demo。如果您将ariaOrientation中的vertical的值更改为foo-chip-list.component.ts,将会看到它如何与堆叠的筹码一起工作。

更新: 发布上述解决方案后,我发现了一个问题。在演示中,单击第三芯片(“ Primary Fish”),然后按向右箭头。您会注意到,选择内容现在移至第一个筹码而不是第四个筹码。这是因为使用鼠标进行选择时activeItemIndex不会更新。为了解决这个问题,我在组件中进行了以下更改,在其中定义了要用作ng-content的芯片:

<foo-chip-list #chipList>
  <mat-chip (click)="selectChip(0)">One fish</mat-chip>
  <mat-chip (click)="selectChip(1)">Two fish</mat-chip>
  <mat-chip (click)="selectChip(2)">Primary fish</mat-chip>
  <mat-chip (click)="selectChip(3)">Accent fish</mat-chip>
</foo-chip-list>

,并在该组件的Typescript中:

@ViewChild('chipList') chipList: FooChipList;

selectChip(index: number) {
  this.chipList.updateSelection(index);
}

然后在FooChipList中,我添加了以下方法:

updateSelection(index: number) {
  this._keyManager.setActiveItem(index);
}

这意味着单击芯片时,它将更新密钥管理器中的活动项目,因此可以进行键盘导航。请参见this StackBlitz进行演示。