My 'awesome' menu:
<mat-menu #appMenu="matMenu">
<ng-template matMenuContent let-myobject="myobject">
<button mat-menu-item>Delete {{myobject.name}}</button>
<button mat-menu-item>Smth else</button>
</ng-template>
</mat-menu>
<button mat-icon-button [matMenuTriggerFor]="appMenu" [matMenuTriggerData]="{myobject: myobject}">
<mat-icon>more_vert</mat-icon>
</button>
First question is if it is ok? Wrote this following documentation but let-myobject="myobject"
and {myobject: myobject}
looks like overhead (?)
Second question is if I want to calculate some data based on myobject
- how I do that? I want it to be calculated just before menu is opened.
[matMenuTriggerData]="getData(myobject)"
- cant make this or similar work
<ng-template matMenuContent let-data="getData(myobject)">
- cant make this or similar work either
I know that I can replace ng-template with component here, but then for e.g. 10 menu items I will need to do 10 outputs in this component. (? or I cant...)
You can certainly pass an object to a mat-menu by using the matMenuTriggerData
directive. This object can contain a single value, another object, or even an array of values or objects. Here's how I solved it:
My challenge was this: I wanted to dynamically build a list of menu items (mat-menu-item
) based on the contents of an array. How did I manage to pass that array of objects to my mat-menu
?
In your component class you can define the array of objects:
export class MyComponent implements OnInit {
menuData: any;
ngOnInit() {
this.menuData = {
menuItems: [
{code: '1', name: 'first'},
{code: '2', name: 'second'}
]
};
}
}
Notice that the object I will pass to the matMenuTriggerData
directive of the button that opens the mat-menu
content, is the data member called menuData
. This member has only one property which is an array of objects. These represent the actual menu items I want to display in my template. The template is shown below:
<mat-menu #app-menu="matMenu">
<ng-template matMenuContent let-aliasMenuItems="menuItems">
<button mat-menu-item *ngFor="let item of aliasMenuItems">
Item {{item.code}}: {{item.name}}
</button>
</ng-template>
</mat-menu>
<button mat-icon-button [matMenuTriggerFor]="app-menu" [matMenuTriggerData]="menuData">
<mat-icon>more_vert</mat-icon>
</button>
Let me explain what is going on in the template: The button defined in the bottom of the template has been linked to the mat-menu
called 'app-menu'
. This is done by typing [matMenuTriggerFor]="app-menu"
.
The next thing we do is passing the component's member data to the mat-menu
through this directive: [matMenuTriggerData]="menuData"
. The mat-menu
instance that we named app-menu
can now grab the content of that member data.
As you can see, the <ng-template>
accesses the property of 'menuData'
that we have named 'menuItems'
. The <ng-template>
adds a pointer or alias to that property (called aliasMenuItems
), like this: <ng-template let-aliasMenuItems="menuItems">
. Now we are able to loop through our defined array of menu items inside the <ng-template>
.
In my example, I create a <button mat-menu-item></button>
element for each menu item object that exists in my component's menuData.menuItems
array, like this:
<button mat-menu-item *ngFor="let item of aliasMenuItems">
Item {{item.code}}: {{item.name}}
</button>
I hope you find this answer useful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With