How to display an overlay with Angular?

Alain Chautard
Angular Training
Published in
4 min readDec 21, 2020

--

In this post, we will explore how to use the Angular CDK (Component Development Kit) to create an overlay that renders some content on top of other content.

The Angular CDK is a library built by the Angular Material team at Google. That said, the CDK itself is independent of any CSS styling, which means it is designed to be agnostic, and you can use it without Angular Material.

CDK Set-up

To use the Angular CDK, all we have to do is add it as a dependency of our Angular project:

npm install @angular/cdk

Once the CDK is installed, we import the overlay module in our application module:

import { OverlayModule } from "@angular/cdk/overlay";

@NgModule({
imports: [BrowserModule, FormsModule, OverlayModule],
declarations: [AppComponent, HelloComponent],
bootstrap: [AppComponent]
})
export class AppModule {}

Once the overlay module is imported, several directives are available for us to use. We will cover those directives shortly.

One last set-up step is to include some base CSS for the Angular CDK in our main styles.css file:

@import '~@angular/cdk/overlay-prebuilt.css';

First overlay example using directives

Now, let’s dive into how a CDK overlay works. An overlay requires three things:

  • A template to render the contents of the overlay on the screen
  • An origin, which is the location where to render the overlay
  • A condition to decide whether to show the overlay or not

In our example, we will create an overlay that shows up as a list of dropdown items. The trigger to show or hide the overlay is going to be a button click.

Let’s create the template for our overlay. It has to be wrapped in an ng-template:

<ng-template>
<ul class="example-overlay">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</ng-template>

Then, we’re going to add our button to the template:

<button>
Open/close overlay
</button>

<div>This content will be under the overlay</div>

<ng-template>
<ul class="example-overlay">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</ng-template>

Now for the CDK to handle the overlay rendering, we’re going to add a few directives to our template.

First, we’re going to define the button as the origin, which means that the overlay will be rendered at the location of the button. This is achieved with the following three directives:

<button cdkOverlayOrigin #trigger="cdkOverlayOrigin">
Open/close overlay
</button>

<div>This content will be under the overlay</div>

<ng-template cdkConnectedOverlay [cdkConnectedOverlayOrigin]="trigger">
<ul class="example-overlay">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</ng-template>

The above directives connect the overlay with its origin, in our case, a button. The button is defined as the cdkOverlayOrigin, and it is set as such on the overlay template using cdkConnectedOverlayOrigin.

The template is also marked as a cdkConnectedOverlay so that the CDK knows that this template will be an overlay.

Pass your Angular certification exam today

Now that our template is connected to an origin, the final step is to define a condition that decides when to render the overlay.

To do so, we add an isOpen property to our component class and initialize it to false, and then we add the following code to our template:

<button (click)="isOpen = !isOpen" cdkOverlayOrigin 
#trigger="cdkOverlayOrigin">
Open/close overlay
</button>

<div>This content will be under the overlay</div>

<ng-template cdkConnectedOverlay
[cdkConnectedOverlayOrigin]="trigger"
[cdkConnectedOverlayOpen]="isOpen">
<ul class="example-overlay">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</ng-template>

The above code provides a condition to show or hide the overlay and a button to toggle that state.

You can see that code in action on StackBlitz below (https://stackblitz.com/edit/cdk-overlay-base)

We could also add some extra features to our overlay, such as hiding it when a click happens outside of it:

<ng-template cdkConnectedOverlay [cdkConnectedOverlayOrigin]="trigger" [cdkConnectedOverlayOpen]="isOpen" (overlayOutsideClick)="isOpen = false">

The full API of events available on our overlay as well as all of the config options for overlays can be found at https://material.angular.io/cdk/overlay/api#CdkConnectedOverlay

Using a service to render components as overlays

Sometimes, we want to render an entire component an overlay, and we want to have full programmatic control over it.

In that case, instead of using directives, we can use the Overlay service from the CDK. In the following example, we inject that service in the constructor of our component, and we add a method that is going to create an overlay using that service and render a component in that overlay:

import { Overlay, OverlayRef } from "@angular/cdk/overlay";
import { ComponentPortal } from "@angular/cdk/portal";
import { Component} from "@angular/core";
import { HelloComponent } from "./hello.component";
@Component({
...
})
export class AppComponent {
overlayRef: OverlayRef; constructor(private overlay: Overlay) {} open() {
// We create the overlay
this.overlayRef = this.overlay.create();
//Then we create a portal to render a component
const componentPortal = new ComponentPortal(HelloComponent);
// We add a custom CSS class to our overlay
this.overlayRef.addPanelClass("example-overlay");
//We render the portal in the overlay
this.overlayRef.attach(componentPortal);
}
}

Then we add the following code to our template. As you can see, there is no overlay directive anymore in that HTML template. The service takes care of everything:

<button(click)="open()">
Open overlay
</button>
<div>This content will be under the overlay</div>

You can see the full code for that second example below (https://stackblitz.com/edit/cdk-overlay-at)

My name is Alain Chautard. I am a Google Developer Expert in Angular, as well as founding consultant and trainer at Angular Training where I help development teams learn and become proficient with Angular.

Need help with Angular? Get in touch.

If you enjoyed this Angular tutorial, please clap for it or share it. Your help is always appreciated.

--

--