Step 13: Angular CDK overlay backdrop fix for menus and selects

Isn’t it annoying when you open an Angular menu or select, the backdrop traps all mouse events? Here’s what I mean:

Note how there’s a mouse hover effect on menu items, but once we open the user menu or the Bitcoin unit select, the effect is gone? It also takes 2 clicks to open the menu if the select options are already open. This is because all mouse events are trapped by the Angular CDK overlay backdrop – a transparent div that takes up the entire viewport. It’s very useful for modals, because we actually want to trap all mouse events in the case of a modal dialog, but why is it done this way for selects and menus? That’s not how the search dropdown and the menu works in Gmail, you know.

We partially solved this in Step 7, by adding [hasBackdrop]="false" to our menu, but that solution was quite ugly, and we weren’t able to solve it for the selects. Here’s a better solution, see styles.scss:

In Angular CDK styles, they set pointer-events to all, and that’s why hover effects and clicks don’t work. Thankfully, we can easily target the transparent backdrop with .cdk-overlay-transparent-backdrop – this distinguishes it from the darker backdrop used for modals, which we don’t want to change.

The only thing we need to add now, is we need to close the menus and selects on document click, see app.component.ts:

We simply click() on the backdrop when we need it, which is on click anywhere in the document, and also on content scroll. We have to subscribe to scoll events on every page change, because our scroller is inside a dynamically created DOM element – for the apps with global scrollers, this would be handled with a simple @HostListener(window:scroll). The nice thing about this solution is that no more code is required anywhere – all menus and selects will now behave. Look, now it works exactly like it should:

I hope you’ll find this helpful, feel free to send me a tip if you do ๐Ÿ™‚