Home > Net >  Angular: close mat-menu after selection of mat-select
Angular: close mat-menu after selection of mat-select

Time:12-21

I have the following HTML code of an Angular app which have a menu for each row. I'm looking for the missing piece of code that would make the closeMe() after selecting a name in the mat-select inside the mat-menu for all the rows not only the first one.

Maybe it's something about #menuContacts which is one name set to access the menu by code but I'm not sure.

<br />
<div *ngFor="let row of rows">
  <div
    style="
      display: inline-flex;
      border: 1px solid black;
      padding: 15px;
      padding-bottom: 3px;
    "
  >
    {{ row }}&nbsp;&nbsp;&nbsp;&nbsp;
    <div
      style="
        position: relative;
        margin-top: -12px;
        border-radius: 50%;
        border: 1px solid black;
        width: 40px;
        height: 40px;
      "
    >
      <button
        mat-icon-button
        [matMenuTriggerFor]="menu"
        #menuContacts="matMenuTrigger"
      >
        <mat-icon>more_vert</mat-icon>
      </button>
    </div>

    <mat-menu #menu="matMenu">
      <button mat-menu-item (click)="selectedRow = row">
        <mat-icon>check</mat-icon>
        <span>{{ row }}</span>
      </button>
      <div style="margin-left: 15px; margin-right: 15px">
        <mat-form-field appearance="outline">
          <mat-label>Name</mat-label>
          <mat-select
            placeholder="Name"
            (click)="$event.stopPropagation();$event.preventDefault"
            (selectionChange)="closeMe()"
          >
            <mat-option *ngFor="let name of names" [value]="name"
              >{{ name }}</mat-option
            >
          </mat-select>
        </mat-form-field>
      </div>
    </mat-menu>
  </div>
  <br />
  <br />
</div>
<br />
<mat-label>Selected row : {{ selectedRow }}</mat-label>

Here's the code behind

import { Component, ViewChild } from '@angular/core';

@Component({
  selector: 'menu-icons-example',
  templateUrl: 'menu-icons-example.html',
  styleUrls: ['menu-icons-example.css'],
})
export class MenuIconsExample {
  @ViewChild('menuContacts') menuContacts;
  rows: [string, string] = ['Row #1', 'Row #2'];
  names: [string, string] = ['Joe Blow', 'Gosh boey'];
  selectedRow: number;

  closeMe() {
    this.menuContacts.closeMenu();
  }
}

You can find the demo here : mat-menu with mat-select

The complete project : Full solution

CodePudding user response:

The problem is that you are using:

@ViewChild('menuContacts') menuContacts;

in order to get each menu trigger.

But ViewChild:

looks for the first element or the directive matching the selector in the view DOM

(docs here: https://angular.io/api/core/ViewChild)

so you will only query the first menu trigger in the DOM (= the menu trigger from the first row).

My solution is to pass the menuTrigger as a parameter to the closeMe() function. The relevant code is below:

closeMe(menuTrigger: MatMenuTrigger) {
  menuTrigger.closeMenu();
}
<button
  mat-icon-button
  [matMenuTriggerFor]="menu"
  #menuContacts="matMenuTrigger">
   <mat-icon>more_vert</mat-icon>
</button>

<mat-select
  placeholder="Name"
  (click)="$event.stopPropagation();$event.preventDefault"
  (selectionChange)="closeMe(menuContacts)">
 ...
</mat-select>

Stackblitz: https://stackblitz.com/edit/mat-menu-epz8dj

  • Related