简体   繁体   中英

Angular MatMenu not working in double ngFor loop

Using Angular 13, I have been trying to add a menu using Angular MatMenu ( https://material.angular.io/components/menu/overview ) which is conditionally shown. Basically a bar shows button (operations) and some may have suboperations. In this case I want to display the suboperations when clicking on the button.

Here is the basic code I have, which is the complete html since there is another menu in the beginning. Note that removing it does not change the behavior.

<div class="rounded-box" *ngIf="!!selectedCategory">
  <div class="selector" *ngIf="rateOrDislocationEnabled; else simpleAggregation">
    <button color="primary" mat-button mat-icon-button [matMenuTriggerFor]="categoryMenu" class="dropdownButton">
      <div class="dropdownText">{{ selectedCategory | agReplace: "_":" " }}</div>
      <mat-icon class="dropdownIcon">arrow_drop_down</mat-icon>
    </button>
    <mat-menu #categoryMenu="matMenu" [overlapTrigger]="true" data-testid="categories-menu">
      <button mat-menu-item *ngFor="let category of availableCategories" (click)="setSelectedCategory(category)">
        <span [ngClass]="{ selectedLabel: isSelected(category) }">{{ category | agReplace: "_":" " }}</span>
        <div *ngIf="category === BlockCategory.RATE_MAKING" class="alpha">ALPHA</div>
      </button>
    </mat-menu>
  </div>
  <ng-container *ngFor="let operationCategory of getOperations(); let lastItem = last">
    <ng-container *ngFor="let operation of operationCategory">
      <button *ngIf="operation.subOperations.length === 0"
              mat-icon-button
              class="iconWrapper"
              id="operation-icon-{{ operation.value }}"
              (click)="addOperation(operation.value)"
              [disabled]="operation.disabled$ | async">
        <mat-icon [ngClass]="operation.icon" class="icon" [agToolTip]="operation.tooltip$ | async"></mat-icon>
      </button>
      <ng-container *ngIf="operation.subOperations.length !== 0">
        <button
          mat-button
          mat-icon-button
          class="iconWrapper"
          id="operation-menu-icon-{{ operation.value }}"
          [matMenuTriggerFor]="subMenu">
          <mat-icon [ngClass]="operation.icon" class="icon" [agToolTip]="operation.tooltip$ | async"></mat-icon>
        </button>
        <mat-menu #subMenu="matMenu">
          <button mat-menu-item>Settings</button>
          <button mat-menu-item>Log off</button>
        </mat-menu>
      </ng-container>
    </ng-container>
    <div class="divider" *ngIf="!lastItem"></div>
  </ng-container>
</div>

I have created a stackblitz reproducing the issue: https://angular-ivy-cvv2xk.stackblitz.io

The issue is that when I click on the button, nothing happens. When I move the button out of the ngFor loops though, it works properly. I have tried things such as removing the ngIf condition (so all buttons are doubled) and none show the menu when clicking on it. So the "submenu" is never displayed.

I wonder if I need to make the mat-menu specific or give it some id to ensure there are no conflicts? Since I'm a bit new to Angular I maybe be missing something.

Thanks in advance

Your button which triggers submenu got multiple button tags.

<button
      mat-button
      mat-icon-button

Can you remove one and try again?


Edit:

You use <ng-container *ngFor="let operationCategory of getOperations(); to populate your array.

If you press your button, angular will trigger change detection and this will trigger again your getOperations() . This will lead to this behaviour and dosent open your submenu.

So you should try to replace getOperations() with async pipe (if this is the case) or use properties.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM