Build a dropdown component using Angular CDK

Ertunga Bezirgan
codeshakeio
Published in
4 min readMay 12, 2021
Photo by Evelyn Paris on Unsplash

In this article, we’ll go through the process of creating a custom, reusable dropdown component with Angular CDK’s overlay module. The way it is consumed will resemble the Angular Material’s menu component.

Let’s go over the requirements

  • Toggle dropdown when the button is clicked
  • When clicked outside or on itself, the dropdown will be closed

Here is what the final result looks like,

Setup

Before we start, make sure to install Angular CDK.

npm install @angular/cdk

Also, add the following prebuilt style to your global stylesheet. By default that would be the styles.scss file under src directory.

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

Overview

Our solution will have a similar approach to Angular Material menu component in the way it is consumed. That means we are going to use a directive that will get the reference for the dropdown it is going to control. Methods that open or close the dropdown will be written inside the directive.

dropdown-panel is the interface that our dropdown component will implement. templateRef holds the reference for the dropdown component template and closed is the EventEmitter that will emit when there is a click on the dropdown itself which then will be used for closing the dropdown.

In the end, this is how it will be used in the application

Toggle Dropdown

To kick things off, let’s create a directive called dropdownTriggerFor. Two important things to mention here:

  • Toggle dropdown method is bound to the host element’s click event
  • Getting dropdown panel via @Input decorator so that we have access to the template reference of the dropdown and the EventEmitter which we will subscribe to close the dropdown

Create an Overlay

The next step will be to create an overlay to which the dropdown will be attached. For that, we will use the Overlay service from Angular CDK and call the create method from the service.

Here is what we need to do,

  1. Create the overlay with this.overlay.create({...}) method.
  2. Using the dropdown panel we got from the @Input, create a TemplatePortal.
  3. Attach TemplatePortal to the overlay using this.overlayRef.attach(...) method.
  4. Start listening to the closing actions, so that we can close the dropdown when it emits a new value.

Now, the create method takes a configuration object as a parameter to customize the overlay behaviour. Let’s go over some of its configurations.

  • scrollStrategy: Configures the behaviour of the overlay during scrolling. Possible options are noop, reposition, block and close.
  • flexibleConnectedTo: Pass in a connection origin for the overlay. This could be an element or element reference or any given (x, y) coordinates within the page. We want to connect the overlay to the button, that’s why we are passing this.elementRef as the connection origin.
  • withPositions: An array of positioning options for the overlay. Sorted from most to least desirable position. For brevity, I will pass in only one option that will render the dropdown underneath the button.

We have created an overlay, now let’s attach our dropdown template to it. We do so by creating a TemplatePortal and pass in the templateRef and the viewContainerRef. Then we are going to attach created TemplatePortal to the overlay using the attach method.

Close Dropdown

Now that we took care of the opening part, let’s look into the scenarios in which we want to close the dropdown. As we stated in the requirements, it should be closed when there is a click on the outside or on itself. Clicks on the dropdown itself will be handled in the dropdown component, we will come to that in a second. Outside clicks can be captured with backdropClick observable. Also, detachments is an observable that emits when the overlay has been detached, that is something we should take into account. And last but not least, throw in the dropdown panel’s closed event emitter in there as well. We will combine them all using merge and subscribe to the resulting merged observable in the openDropdown method.

To close the dropdown, we will call the destroyDropdown method which will detach the overlay.

Create a Dropdown Component

The component is pretty simple. Just wrap ng-content with a div and add some style to it. As mentioned before, we will use closed here to emit a new value when there is a click on the dropdown itself.

We will also implement dropdown-panel interface.

Done! 🎉

And that’s really it! We’ve seen how Angular CDK overlay can be used to create a reusable dropdown component and we are only scratching the surface here. CDK modules can help you develop many more kinds of components. Dialog, toast, drawer, tooltip, popover just to name a few.

Hope you find this article helpful. If you have any questions, don’t hesitate to drop a comment. 👋

--

--