0

I have a case where I'd like to add a context menu to each line of a generated list or table in Angular Material, something like:

<mat-list *ngFor="let item of itemlist">
    <mat-list-item>
        <some-component [item]="item"></some-component>
        <button mat-button [matMenuTriggerFor]="menu">Menu</button>

        <mat-menu #menu="matMenu">
          <button *ngFor="let option of options" mat-menu-item (click)="fire(item, option)">
            {{ option }}
          </button>
        </mat-menu>
    </mat-list-item>
</mat-list

where "some-component" displays whatever the item is, on a single line. The problem is that the menus items don't call the fire method when they're clicked. My guess is that this is because the menus need their own IDs, but I can't figure out how to do that programatically. I looked at ng-attr-id, but couldn't figure out how to use that with the #menu="matMenu" syntax. Here's a Stackblitz that has a more detailed example of what I'm after.

15

1 Answer 1

1

Thanks to the generous help of Ashot Aleqsanyan, the fix for this is to prevent the list of options from being re-rendered. The issue is that the button(s) associated with the items in the list are removed from the DOM when the list is re-rendered. One way to do this (described here) is to use the trackBy element of ngFor, like this:

<button
    *ngFor="let option of options; trackBy: onTrackByFunction"
    mat-menu-item (click)="fire(item, option)">

in the HTML, and this:

onTrackByFunction(index: number, item: any) {
    return index
}

in the Typescript.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.