angularangular-materialangular-cdk

How to open a particular menu programmatically if more than one menu element - angular cdk menu


How to open a particular menu programmatically if more than one menu element - angular cdk menu

As given below code for menu 1 and menu 2, I need to create @ViewChild(CdkMenuTrigger) trigger: CdkMenuTrigger; for menu 2 programmatically but by default it capture menu 1 always, so how we can create object for particular menu programmatically? Please note both code in same file.. For Refs - Open Angular CDK Menu programatically

Code Menu 1-

<button [cdkMenuTriggerFor]="menu" class="example-standalone-trigger">Click me!</button>

<ng-template #menu>
  <div class="example-menu" cdkMenu>
    <button class="example-menu-item" cdkMenuItem>Refresh</button>
    <button class="example-menu-item" cdkMenuItem #settings>Settings</button>
    <button class="example-menu-item" cdkMenuItem>Help</button>
    <button class="example-menu-item" cdkMenuItem>Sign out</button>
  </div>
</ng-template>

Code Menu 2 -

<button [cdkMenuTriggerFor]="menu2" class="example-standalone-trigger">Click me!</button>

<ng-template #menu2>
  <div class="example-menu" cdkMenu>
    <button class="example-menu-item" cdkMenuItem>Menu Item1</button>
    <button class="example-menu-item" cdkMenuItem>Menu Item2</button>
    <button class="example-menu-item" cdkMenuItem>Menu Item3</button>
    <button class="example-menu-item" cdkMenuItem>Menu Item4</button>
  </div>
</ng-template>


Solution

  • I need to create @ViewChild(CdkMenuTrigger) trigger: CdkMenuTrigger; for menu 2 programmatically but by default it capture menu 1 always, so how we can create object for particular menu programmatically?

    So, whenever you try to get a trigger for menu2, you are ending up getting a trigger for menu1. It is what I understood from your comments.

    The reason for that is @ViewChild looks for the first element or the directive matching the selector in the view DOM.

    The First Approach

    You can use @ViewChildren instead.

    @ViewChildren return a QueryList object that contains the query results (all the triggers).

    To get a particular trigger, you can use get(index) method.

    @ViewChildren(MatMenuTrigger) triggers: QueryList<MatMenuTrigger>;
    
    
     someMethod() {
        this.triggers.get(1).openMenu();
      }
    

    The Second Approach

    If you do not want to use @ViewChildren, you can still keep using @ViewChild but you should distinguish your second trigger.

    Among others, below selectors are supported by @ViewChild

    So,

    html template:

    <button 
    #menuTrigger2="matMenuTrigger"
    [cdkMenuTriggerFor]="menu2" 
    class="example-standalone-trigger">
       Click me!
    </button>
    
    

    component.ts:

    @ViewChild('menuTrigger2') trigger!: MatMenuTrigger;
    
     someMethod() {
        this.trigger!.openMenu();
      }