mat-menu and button in different components
Well, if you want to do something like this:
<button mat-button [matMenuTriggerFor]="menu">Menu</button>
<other-component [matMenu]="menu"></other-component>
<mat-menu #menu="matMenu">
<button mat-menu-item>Item 1</button>
<button mat-menu-item>Item 2</button>
</mat-menu>
You can code <other-component>
like this:
import {Component,Input} from '@angular/core';
import {MatMenu} from '@angular/material/menu';
@Component({
selector: 'other-component',
template: `
This button is in another component:
<button [matMenuTriggerFor]="matMenu">Click here to open menu</button>
`,
})
export class OtherComponent {
@Input() matMenu: MatMenu;
}
You can see the above example working at this stackblitz demo.
Another approach
Another approach is (I think this is what you want): your trigger button is inside the parent (but outside the child) and the menu itself is defined inside the child component.
Parent component:
<button mat-button [matMenuTriggerFor]="childComponentMenu?.menu">
Menu in other component
</button>
<child-component></child-component>
export class ParentComponent {
@ViewChild(ChildComponent) childComponentMenu: ChildComponent;
}
Child Component:
@Component({
selector: 'child-component',
template: `
<mat-menu>
<button mat-menu-item>Item 1 (inside other component)</button>
<button mat-menu-item>Item 2 (inside other component)</button>
</mat-menu>
`,
})
export class ChildComponent {
@ViewChild(MatMenu, {static: true}) menu: MatMenu;
}
Yet Another approach
Another approach, similar to the above one, but using template reference variables (notice the exportAs
in the decorator of the child component):
Parent component:
<button mat-button [matMenuTriggerFor]="x.menu">
Menu in other component
</button>
<child-component #x="menuInOtherComponent"></child-component>
export class ParentComponent {
}
Child Component:
@Component({
selector: 'child-component',
template: `
<mat-menu>
<button mat-menu-item>Item 1 (inside other component)</button>
<button mat-menu-item>Item 2 (inside other component)</button>
</mat-menu>
`,
exportAs: 'menuInOtherComponent',
})
export class ChildComponent {
@ViewChild(MatMenu, {static: true}) menu: MatMenu;
}
Stackblitz demo
Here's another solution using ng-content
. That's my preferred way to go.
my-custom-menu-component html:
<div [matMenuTriggerFor]="menu">
<ng-content></ng-content>
</div>
<mat-menu #menu="matMenu">
menu content
</mat-menu>
parent-component html:
<my-custom-menu-component>
<button>click me</button>
<my-custom-menu-component>