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 }}
<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