Search code examples
angularperformancedrop-down-menuangular-material

Mat-menu in for loop: performance issues


I want to use the mat-menu of Material in Angular as a dropdown directive and found a way to manipulate it so that it would fit the needs of our application (see related question here: Override Angular Material Component)

Now I integrated the mat-menu in our component. But the menu opens and closes very slowly. It may be related to the issue that the mat-menu is inside a child component of a for loop, so many mat-menus will be generated.

I created a stackblitz to show the issue: https://stackblitz.com/edit/angular-uzlezn-nh7dbu?file=app/menu-icons-example.html

The first 'test test' is a mat-menu which is not inside a for-loop. Here it opens and closes at a reasonable time.

The 'bla bla' mat-menus are inside a loop. And when you click around with them you see that sometimes a mat-menu at the beginning would open too and to close the menu you would need to click twice. I think this happens because you need to click to close it for each menu.

Now I think this happens because each menu has the same template-name (although I read that it is not an issue when the mat-menu is inside a loop because each menu would get its own scope).

I also tried surrounding the loop with ng-container but that also didn't increased the performance.

Has somebody an idea what I could do to improve the performance or could suggest a different alternative for a dropdown with Angular (5)?


Solution

  • I dont see any performance issue here, the script has loaded within seconds and to point your issue where first menu opens while clicking on others because you no need open the menu from any method, its default functionality of menu to open options. I have updated your code below please check. Remove somemthod function from input type or you can perform any other functionality except trigger open

       <span mat-icon-button #notificationMenuBtn 
        [matMenuTriggerFor]="menu1">
        test test
       </span>
       <mat-menu #menu1="matMenu" (click)="$event.stopPropagation()" 
        [xPosition]="'after'" [overlapTrigger]="false">
        <input (mouseenter)="someMethod1()" 
         (click)="$event.stopPropagation()"><button 
         (click)="$event.stopPropagation()">OK</button>
       </mat-menu>
    
       <div *ngFor="let i of loop">
        <span mat-icon-button #notificationMenuBtn 
         [matMenuTriggerFor]="menu">
          bla bla
        </span>
        <mat-menu #menu="matMenu" (click)="$event.stopPropagation()" 
         [xPosition]="'after'" [overlapTrigger]="false">
           <input (mouseenter)="someMethod2()" 
           (click)="$event.stopPropagation()"><button 
           (click)="$event.stopPropagation()">OK</button>
        </mat-menu>
        <br>
      </div>