Using Angular Material Dialog during Fullscreen

Introduction

I was working on an Angular project in my workplace recently. And I ran into a situation where I need to show Dialog when the application is in a fullscreen mode. Well, part of the dom tree in fullscreen mode to be specific. The project is relying on Angular Material's Dialog.

And guess what, out of the box, it doesn't work. The Dialog just doesn't show up during fullscreen mode.

Reason being, the dialog or rather the overlay element is rendered at the HTML's Body level by default. In order to show the dialog in a "fullscreen region", the overlay element has to be rendered within the "fullscreen region".

By "fullscreen region", I am referring to the element that is in fullscreen mode, mostly invoked via the Web API's requestFullscreen method.

Motivation

And SO! I set out to Google around and dig quite a bit into the Angular Material's documentations. Luckily, there is a solution for this! The answer lies in the last tiny paragraph of this documentation.

This article is written, in hope to help some Angular lost souls out there who was in the same situation where I was. Hopefully, it saves you some precious amount of time!

Topics Coverage

Please feel free to skip to the sections of your interest.

  1. Sample Project
  2. Code Configurations
  3. How It Works?

Sample Project

I have created a sample Angular project to demo the fullscreen configurations and usage for it.

The source codes can be found here https://github.com/DriLLFreAK100/ng-dialog-fullscreen-sample

Code Configurations

Open up the module file where you import your MatDialogModule. Be careful, this is very very very important! It will only work if you provide the config at that particular module.

If you are breaking up your application in multiple modules, e.g. SharedModule, etc. or something like that to handle MatDialog separately, you might wanna inject this config in that module file.

So, it is like what it was documented in the official doc's last paragraph. You need to include the following in the providers. We're basically swapping in the FullscreenOverlayContainer to override the default OverlayContainer.

1providers: [
2    { provide: OverlayContainer, useClass: FullscreenOverlayContainer },
3]
4

My full module config looks something like this:

1import { AppComponent } from './app.component';
2import { AppRoutingModule } from './app-routing.module';
3import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
4import { BrowserModule } from '@angular/platform-browser';
5import { MatButtonModule } from '@angular/material/button';
6import { MatCardModule } from '@angular/material/card';
7import { MatDialogModule } from '@angular/material/dialog';
8import { MatIconModule } from '@angular/material/icon';
9import { NgModule } from '@angular/core';
10import { SampleDialogComponent } from './components/sample-dialog/sample-dialog.component';
11import {
12  FullscreenOverlayContainer,
13  OverlayContainer,
14} from '@angular/cdk/overlay';
15
16@NgModule({
17  declarations: [AppComponent, SampleDialogComponent],
18  imports: [
19    AppRoutingModule,
20    BrowserAnimationsModule,
21    BrowserModule,
22    MatButtonModule,
23    MatCardModule,
24    MatDialogModule,
25    MatIconModule,
26  ],
27  providers: [
28    { provide: OverlayContainer, useClass: FullscreenOverlayContainer },
29  ],
30  bootstrap: [AppComponent],
31})
32export class AppModule {}
33

Note that you can also provide your own class to override the OverlayContainer render behavior. It is covered in this Stackoverflow's answer. You can manipulate the _createContainer function and include your own logics to find the element to render upon.

How It Works?

Let's take a deeper look at how the Overlay element is rendered upon our HTML.

By default, without the configuration in the section above, the Angular Material's Overlay will always be rendered at the HTML Body.

default behavior
https://github.com/DriLLFreAK100/ng-dialog-fullscreen-sample/blob/main/samples/Default.png

Even if we entered fullscreen mode in a child dom within the Body node, the Overlay element will still be rendered at the Body node.

That is the reason why we are not able to see the Dialog during fullscreen. In this example, the element in fullscreen is the one being highlighted on top. As you can see, it is a sibling node's child to the Overlay element. Hence, it was not able to show during its fullscreen.

fullscreen not working
https://github.com/DriLLFreAK100/ng-dialog-fullscreen-sample/blob/main/samples/Fullscreen%20-%20not%20working.png

After the providers are being included, the dialog finally shows up! If we observe carefully, the Overlay element is being rendered within the fullscreen element now. Magic! 😛

fullscreen working
https://github.com/DriLLFreAK100/ng-dialog-fullscreen-sample/blob/main/samples/Fullscreen%20-%20work.png

Conclusion

It is possible to show Angular Material's Dialog within an element's fullscreen mode. We just have to include a provider to override the default OverlayContainer class.

Honestly, I wasn't too optimistic that there was a solution for it in the beginning since things are very much framework-oriented in Angular world. But hey, I am really glad that this kind of edge case was handled. That was very sweet! Thanks Angular Material team! haha..

Overall, I still find it pretty hard to navigate and dig around this kind of override topics within the Angular space. Perhaps, I am still not too deeply attached with Angular yet. Hahaha.. Hopefully, I'll be able to write and share more on those in near future 🙂

P.S.

Speaking of which... Recently, I have joined a new team in my workplace. Many moving parts and learnings to do since the frontend tech stack is quite different from where I was coming from (React). Nevertheless, it's both challenging and interesting at the same time! We're utilizing Nx Monorepo, Angular and Stencil heavily to build tons of cool analytic stuffs here.

Well, not all new too, since I was once from the "Angular camp" some years ago if you're following my previous posts. It's more of a "reunion" in the sense 😛 But hey, I'm missing React already. Sigh... Haha...

Things are definitely much easier to grasp in React, and there are tons of spaces for creativity since the library is mostly not opinionated. And man, it was wayyyyyyyyy predictable and easier to trace than Angular, since it's mostly a single downright render.

Well, let's see how it goes a few months down the road. Who knows I might have a change in taste hmmmm hahaha...


Coffee time! Very nice coffee beans from Apartment Coffee. It was the Columbia Shady Bader Gesha. Had lots of fun brewing with this one!

columbia coffee beans

References

  1. https://material.angular.io/cdk/overlay/overview
  2. https://stackoverflow.com/questions/55288559/angular-cdk-overlay-change-default-overlay-container/55289312#55289312