htmlangularangular-materialngforng-template

Angular mat-menu in ng-template with ngFor


I'm trying to create an ng-template with ngFor instead of duplicated mat-menus in my html. But I'm having trouble with the menu trigger. I understand it needs to be unique for the trigger to work but I can't seem to do it.


  <ng-template ngFor let-filter let-i="index" [ngForOf]="filters()">
    <button mat-button
            [matMenuTriggerFor]="i"
            #filterMenu="matMenuTrigger">
      {{filter.title | translate}}
 
    </button>

    <mat-menu #i="matMenu">
      <button mat-menu-item
              *ngFor="let option of filter.values"
              [value]="option">
        <span>{{ option }}</span>
      </button>
    </mat-menu>
  </ng-template>

Solution

  • I think you are looking for ng-container, which can be iterated with *ngFor there is no need for ID, we can just pass the template reference directly.

    HTML:

    <ng-container *ngFor="let filter of filters">
      <button mat-button [matMenuTriggerFor]="i" #filterMenu="matMenuTrigger">
        {{filter.title}}
      </button>
    
      <mat-menu #i="matMenu">
        <button mat-menu-item *ngFor="let option of filter.values" [value]="option">
          <span>{{ option }}</span>
        </button>
      </mat-menu>
    </ng-container>
    

    TS:

    import { Component } from '@angular/core';
    import { MatMenuModule } from '@angular/material/menu';
    import { MatButtonModule } from '@angular/material/button';
    import { CommonModule } from '@angular/common';
    
    /**
     * @title Menu positioning
     */
    @Component({
      selector: 'menu-position-example',
      templateUrl: 'menu-position-example.html',
      standalone: true,
      imports: [MatButtonModule, MatMenuModule, CommonModule],
    })
    export class MenuPositionExample {
      filters = [
        {
          title: 'first',
          values: ['one', 'two', 'three', 'four'],
        },
        {
          title: 'second',
          values: ['one', 'two', 'three', 'four'],
        },
        {
          title: 'three',
          values: ['one', 'two', 'three', 'four'],
        },
        {
          title: 'four',
          values: ['one', 'two', 'three', 'four'],
        },
      ];
    }
    

    Stackblitz Demo