Tachyon
Tachyon

Reputation: 2411

Can't click button in tab header/label in Angular 15

I am currently trying to implement a tab feature using Angular Material. I can for the life of me not get the button to click that is in the header. I have tried moving the click event around the tabs and it doesn't seem to get triggered anywhere.

I am trying to add the functionality that you can close a tab by clicking on the close icon. I have tried putting it in a div. I've tried using a div instead of a button.

Here is the UI:

 <mat-tab-group animationDuration="0ms">
    <div *ngIf="tabs">
      <mat-tab *ngFor="let tab of tabs; let index = index" [ngSwitch]="tab.type">
        <ng-template mat-tab-label>
          <div style="display: flex; flex-direction: row; align-items: center;">
            {{tab["title"]}}
            <div>
              <button style="color:black" mat-icon-button (click)="closeTab($event, index)">
                <mat-icon>close</mat-icon>
              </button>
            </div>
          </div>
        </ng-template>
        <div *ngSwitchCase="'Work'">
          <p>Work</p>
        </div>
        <div *ngSwitchCase="'Case'">
          <p>Case</p>
        </div>
        <div *ngSwitchCase="'Document'">
          <app-base></app-base>
        </div>
      </mat-tab>
    </div>
  </mat-tab-group>
</div>

And the backend:

import {MatTab, MatTabGroup} from '@angular/material/tabs';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})

export class HomeComponent {
  @ViewChild(MatTabGroup, {read: MatTabGroup})
  public tabGroup: MatTabGroup;
  @ViewChildren(MatTab, {read: MatTab})
  public tabNodes: QueryList<MatTab>;

  tabs: Tab[] = [];
  workCounter: number = 0;
  caseCounter: number = 0;
  documentCounter: number = 0;
  closedTabs: number[] = [];

  ngOnInit(): void {

  }

  addNewTab(type: string): void {
    let tab = new Tab();

    switch (type) {
      case 'Work':
        this.workCounter++;
        tab.type = type;
        tab.title = `${type} # ${this.workCounter}`
        break;
      case 'Document':
        this.documentCounter++;
        tab.type = type;
        tab.title = `${type} # ${this.documentCounter}`
        break;
      case 'Case':
        this.caseCounter++;
        tab.type = type;
        tab.title = `${type} # ${this.caseCounter}`
        break;
    }

    this.tabs.push(tab);
  }

  closeTab(event: Event, index: number) {
    console.log(index);
    event.stopPropagation();
    this.closedTabs.push(index);
    this.tabGroup.selectedIndex = this.tabNodes.length - 1;
    console.log(index);
  }
}

class Tab {
  type: string;
  title: string;
  index: number;
}


Upvotes: 4

Views: 1733

Answers (4)

Lys
Lys

Reputation: 825

in order to have a button in the tab header but not be a real tab, but be clickable and not look disabled you can add this to your style.scss

.mdc-tab.mat-mdc-tab:has(.fake-disabled){
  opacity: initial;
  .mdc-tab__content {
    pointer-events: all;
  }
}

and add a mat-tab disabled to html. you will need to add a class "fake-disabled" to your button

     <ng-template mat-tab-label>
        <mat-icon (click)="doStuff()" class="fake-disabled">add_circle</mat-icon>
     </ng-template>
   </mat-tab>

Upvotes: 0

Jim Jimson
Jim Jimson

Reputation: 2518

To add something a little more specific here, the material design specification doesn't mention anything about being able to close tabs.

However there is mention of the fact that if an element has point-events: none, but one of its descendants has pointer-events:auto then:

pointer events will trigger event listeners on this parent element as appropriate on their way to/from the descendant during the event capture/bubble phases

You can read more about that here.

So, instead of blanket applying pointer-events:all to all of your tabs, you can simply add it to the style of the icon:

<mat-icon style="pointer-events: auto;" *ngIf="index > 1" (click)="removeTab(index)">{{tab.icon}}</mat-icon>

Or I guess you could make a clickable-icon class:

.clickable-icon {
    pointer-events: auto;
}

There are currently two issues open in the angular/components repo here and here that you can keep an eye on for resolution.

Upvotes: 4

Minute Illimit&#233;e
Minute Illimit&#233;e

Reputation: 101

try adding this to your style.css file

   .mdc-tab__content{
      pointer-events: all!important;
    }

Upvotes: 1

Mr. Stash
Mr. Stash

Reputation: 3130

Found the problem, Material 15 has added pointer-events rule and sets it to None, overriding this should allow click events to call the ts methods

<mat-tab-group animationDuration="0ms" class="allow-tab-events">
</mat-tab-group>
.allow-tab-events ::ng-deep .mdc-tab .mdc-tab__content{
  pointer-events: all;
}

Upvotes: 4

Related Questions