Sadiinso
Sadiinso

Reputation: 315

Angular - Access elementRef of MatMenu

I have the following setup:

@Directive({
    selector: '[test]'
})
export class Test {
    constructor(
        private hostRef: ElementRef,
        private host: MatMenuTrigger,
    ) {}

    ngOnInit() {
        this.host.menuOpened.subscribe(() => {
            /* Do something with the MatMenu elementRef */
        });
    }
}
<a [matMenuTriggerFor]="aMenu" test></a>
<mat-menu #aMenu></mat-menu>

I want to get the ElementRef of the MatMenu (not a reference to the opened MatMenu component nor the elementRef of the MatMenuTrigger). After looking at the typescript definition file for the MatMenu class, I came across the _elementRef private property which allows me to access the elementRef like so:

this.host.menuOpened.subscribe(() => {
    const ref = (this.host.menu as any)._elementRef;
    /* Do something with ref */
});

The only problem is that this is relying on the Angular team maintining this property in the future versions (and, well, the fact that this is a private property to begin with).

I could put the test directive directly on the mat-menu template, which would allow me to access its elementRef using the ElementRef injector, but I would loose access to the MatMenuTrigger functions such as openMenu and closeMenu (a MatMenu instance does not hold any reference to any of its associated MatMenuTrigger).

Is there a way to access the ElementRef of a MatMenu without using its private properties (or a way to close a MatMenu without having access to an associated MatMenuTrigger) ?
I need the ElementRef to test whether a click on the document came from the Menu (by testing if the menu elementRef is included inside the event composedPath)

Upvotes: 4

Views: 1253

Answers (1)

Will Alexander
Will Alexander

Reputation: 3571

It sounds like you're trying to pass the reference to the mat-menu element to your test Directive. If that's the case, try adding an Input() to the Directive:

@Input() menu: MatMenu;

Then in your template:

<a [matMenuTriggerFor]="aMenu" test [menuRef]="aMenu"></a>
<mat-menu #aMenu></mat-menu>

That way, you pass the component via local reference to your Directive.

Upvotes: -1

Related Questions