How to change the tabindex for mat-tab as it is 0

Viewed 703

In the below code I have 3 tab-group. When I am switching from one tab group to another using tab key, it is in a sequence. I want to change the sequence, so applied tabindex to mat-tab, but it is not working. The tabindex is not changing, it remains 0.

Css:

.mat-tab-group {
  margin-bottom: 48px;
 }

HTML:

<mat-tab-group mat-align-tabs="start">
  <mat-tab tabindex="2" label="First">Content 1</mat-tab>
  <mat-tab label="Second">Content 2</mat-tab>
  <mat-tab label="Third">Content 3</mat-tab>
</mat-tab-group>

<mat-tab-group mat-align-tabs="center">
  <mat-tab tabindex="1" label="First">Content 1</mat-tab>
  <mat-tab label="Second">Content 2</mat-tab>
  <mat-tab label="Third">Content 3</mat-tab>
</mat-tab-group>

<mat-tab-group mat-align-tabs="end">
  <mat-tab tabindex="3" label="First">Content 1</mat-tab>
  <mat-tab label="Second">Content 2</mat-tab>
  <mat-tab label="Third">Content 3</mat-tab>
</mat-tab-group>

check out the link: https://stackblitz.com/edit/angular-xtv9to?file=src%2Fapp%2Ftab-group-align-example.html

got a reference tabIndex doesn't work on mat-tab (Angular 7) but this is the answer I need.

1 Answers

Perhaps this could help you, it is a directive that listens to the tab key events and then selects the next mat-tab-group in the sequence you need. The code has some comments so you can understand what im doing.

@Directive({
  selector: "mtabindex"
})
export class TabDirective implements AfterViewInit {
  @ContentChildren(MatTabGroup) private groups: QueryList<MatTabGroup>;

  private tabGroups: { tabindex: number; node: any }[] = [];

  constructor(
    private container: ViewContainerRef,
    private cdr: ChangeDetectorRef
  ) {}

  /**
   * Creates an array of the tab groups with the attribute [tabindex]
   * Appends the node element and the tabindex number
   */
  ngAfterViewInit(): void {
    (this.container.element.nativeElement as HTMLElement).childNodes.forEach(
      (e: any & HTMLElement) => {
        const tabindex = e.attributes.getNamedItem("tabindex")!.value;
        this.tabGroups.push({
          tabindex,
          node: e
        });
      }
    );
  }

/**
 * Listen to the keydown events in mat-tab-groups
 */
  @HostListener("keydown", ["$event"])
  onTab($event: KeyboardEvent) {
    if ($event.code == "Tab") {
      
      const tabGroup: HTMLElement = this.getCurrentTabGroup($event);

      const currentGroup: number = Number(
        tabGroup.attributes.getNamedItem("tabindex")!.value
      );

      const nextTabGroup = this.getTabGroup(currentGroup);
      /**if there is a mat-tab-group then continue*/
      if (nextTabGroup.tabGroupIndex != -1) {
        $event.preventDefault();
        this.handleClick(nextTabGroup);
      }
    }
  }

/**
 * Returns the current mat-tab-group where the tab-key was pressed
 */
  private getCurrentTabGroup(event: Event): HTMLElement {
    return event
        .composedPath()
        .find(e =>
          (e as HTMLElement).classList.contains("mat-tab-group")
        ) as HTMLElement;
  }

/**
 * Creates an object with the element mat-tab-group and his current index
 */
  private getTabGroup(index: number): {tabGroup: any, tabGroupIndex: number} {
    return {
      tabGroup: this.tabGroups.find(e => e.tabindex >= index + 1)?.node,
      tabGroupIndex: this.tabGroups.findIndex(e => e.tabindex >= index + 1)
    };
  }

/**
 * Changes the selected index in the next mat-group and focus the mat-tab
 * The selected tab will be 0
 */
  private handleClick(nextTabGroup: {
    tabGroup: any;
    tabGroupIndex: number;
  }): void {
    this.groups.get(nextTabGroup.tabGroupIndex)!.selectedIndex = 0;
    nextTabGroup.tabGroup.children[0].children[1].children[0].children[0].children[0].focus();
    this.cdr.detectChanges();
  }
}

In your html wrap all mat-tab-group's with the directive and put the [tabindex] attribute.

<mtabindex>
  <mat-tab-group [tabindex]="2" mat-align-tabs="start">
    <!-- #enddocregion align-start -->
    <mat-tab label="First1">Content 1</mat-tab>
    <mat-tab label="Second1">Content 2</mat-tab>
    <mat-tab label="Third1">Content 3</mat-tab>
  </mat-tab-group>

  <mat-tab-group [tabindex]="1" mat-align-tabs="center">
    <mat-tab label="First2">Content 1</mat-tab>
    <mat-tab label="Second2">Content 2</mat-tab>
    <mat-tab label="Third2">Content 3</mat-tab>
  </mat-tab-group>

  <mat-tab-group [tabindex]="3" mat-align-tabs="end">
    <mat-tab label="First3">Content 1</mat-tab>
    <mat-tab label="Second3">Content 2</mat-tab>
    <mat-tab label="Third3">Content 3</mat-tab>
  </mat-tab-group>
</mtabindex>

This is just an idea, maybe you could improve this approach.

Related