Don’t fear the CDK

It’s not hard to create custom UI

Erik Tallang
Compendium
5 min readAug 27, 2018

--

A common pattern among developers using Angular Material is to use the framework on every piece of UI, even UI that is custom to the application they create and therefore outside the scope of how Angular Material is intended to work. Sometimes this is only a matter of tweaking the CSS a bit for a component, while other times functional changes needs to be made. This can be troublesome and the result may contain ugly hacks that’s hard to maintain and keep bug free. I wish to bring some attention to Angular CDK, a component development kit that may be exactly what you need to create your application-specific component. We’ll look into the OverlayModule, and how it helps us to create a custom snack bar.

The finished snack bar example can be viewed on StackBlitz, while the code is hosted on GitHub.

The art of opinion

While creating a custom component from scratch is harder than using an existing one, creating a component that tries to be configurable in every way increases the complexity by an enormous magnitude. So do yourself a favor and keep the component as opinionated as possible. This depends on your components purpose naturally, as an application-specific component can be very opinionated, while for example a component intended for a shared NPM package may have more flexibility in how it’s used. A component created for a specific application may actually have an advantage of being opinionated, as this emphasizes its intended usage, limiting how may different ways the developers on the team may use your component. This is one of many ways of keeping the user experience consistent across your entire application.

Meet the CDK

When the Angular team worked on Angular Material, they came across pieces of UI behavior that was similar between different components. This discovery became the motivation to create Angular CDK, a library that contains low level building blocks for creating components. At the time of writing this article, the library provides three components, which is a stepper, table and tree. These components have no opinion on styling, which makes these components perfect if you wish to design them yourself. The library also contains a couple of handy utility-modules. One of them is the A11yModule which among other things provides a FocusKeyManager to control tab focus. This is useful when creating popups where you want to trap the focus until it has been closed. Another utility in the CDK is the OverlayModule. This module works as a foundation to create menus, dialogs, tooltips and any kind of UI that should be placed above other elements in the DOM (hence the name). We’ll use this module to create a snack bar, which is a component that’s commonly used to show feedback to the user.

Creating the project and setting up our module

Install the Angular CLI globally if you haven’t, and generate a new project. We’ll also create a new module for our snack bar (referenced to as feedback from now on) with a corresponding component and service.

In order to use the features of the Angular CDK, we have to add it to our project. Add it by using either NPM or Yarn.

Since we’ll be using the OverlayModule from Angular CDK, we must import it in our FeedbackModule. Our FeedbackComponent must also be added to the entryComponents-array in our module, since it will be added to the DOM dynamically. Our FeedbackModule should now look like this:

Providing overlay style to our feedback component

To keep this article reasonably short, I won’t talk about styling the feedback component, nor how to animate it in our out. The only thing to remember about the styling, is to import the overlay styling from the Angular CDK project.

This can be done anywhere in your project, but it has to be globally available. If you do it from your FeedbackComponent you have to remember to disable the view encapsulation by setting ViewEncapsulation.None. The feedback component can be made as simple or complex as you want. A good tip is still to have the text to display as a variable in your component, and then bind it to the HTML so that developers can provide whatever message they want.

You may also add other properties to for example show/hide a close-button, change the severity of the feedback, or whatever else you would like to add. If you wish to grab the remaining SCSS and animations from my demo, it’s available in the GitHub project.

Using the overlay service

The real magic in this example happens in the feedback.service.ts. I’ll display the service in its entirety and then explain it piece by piece:

The wonders of the Overlay-service is seen in the constructor of the service. The service has a create-function that takes a configuration object where you specify how your overlay should behave. Pay extra attention to the beautiful design of the positionStrategy property. Each of the methods are chainable, creating a very readable position definition for your overlay. The position is also easy to modify later on, if you maybe want to give the developer the possibility to align the feedback wherever he/she wants.

The only thing exposed from the service is the openFeedback-method that takes a message and an optional options-object where the developer can set a few options that we have implemented. Notice the use of Partial for the options, as this makes every property on the FeedbackOptions interface optional.

The first thing we check is if there is an existing overlay active. If so, we detach it, which in practice means removing it from the DOM. We then create a ComponentPortal of our FeedbackComponent and attach it to the overlayRef we created in the constructor. I’ve also taken the liberty of setting the message and options object in the component instance. That’s basically it. When calling the openFeedback-method, the FeedbackComponent will be inserted into the DOM on the position we specified in the constructor, and the message and options will be set. The feedback in the GitHub demo also has a timeout so that the feedback is removed after 4s, or whatever custom timing the developer provides.

It’s not so hard

The service we created to display the feedback consisted of a total of 39 lines of code. That’s it. That includes imports. Considering that we now have full control of the features and visuals of the feedback, that’s a very affordable custom implementation that I would choose any time in favor of hacking a premade NPM package in order to make it work the way I want. The CDK is also under active development, and new features is regularly added to the library. I hope this small example served to take the edge off some developers out there, to dare to take a step into the CDK to see what tools it has to offer.

--

--