Don’t fear the CDK
It’s not hard to create custom UI
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 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
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
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.