How I Built A Custom Stepper/Wizard Component Using The Angular Material CDK
Update 12.02.2018: Meanwhile, I have created a PR to the Angular Material repository and added there an official guide
I recently had to refactor a quite complex legacy Angular component and want to share my experiences with you.
The Legacy Component
The component should look this way per design:
You can freely navigate through the content by clicking either the navigation arrows or clicking on a certain step in the navigation area at the bottom.
The HTML template of the legacy component looked similar to this simple example:
So basically, there was a div
container for each content page with multiple *ngIf
statements. As only one content container could be visible per time, the *ngIf
directives controlled their visibility.
Maybe at first glance, this sounds not that bad for you, but this approach had some significant problems:
- It contained large and confusing
ngIf
statements. - Accessibility was not considered.
- Keyboard interactions were not supported by default.
- Managing which state is active had to be implemented manually.
- It is a custom solution that needs to be tested.
- It provided a non-scalable component architecture.
Additionally, we got a new requirement: It should be possible to switch between the content pages linearly. That means going from the first content page to the second content page should only be possible if the first page is completed, and going backward should not be allowed.
Refactoring
To fulfill the new requirement, I started research for existing components that provide a similar logic and found, for example, Angular Archwizard.
This excellent component also worked fine with the latest Angular version, but I could not easily modify the styling for our design requirements.
So I continued my research and stumbled upon the Angular Material CDK Stepper, which was exactly what I was looking for.
Angular Material CDK
On the official website, they describe the Component Dev Kit (CDK) as:
The Component Dev Kit (CDK) is a set of tools that implement common interaction patterns whilst being unopinionated about their presentation. It represents an abstraction of the core functionalities found in the Angular Material library, without any styling specific to Material Design. Think of the CDK as a blank state of well-tested functionality upon which you can develop your own bespoke components.
The CDK is divided into two parts: "Common Behaviors" and "Components".
Common Behaviors
Tools for implementing common application features
This is a list of common behaviors provided by the CDK:
Components
Unstyled components with useful functionality
The following image shows the list of components provided by the CDK:
CDK Stepper
The CdkStepper was exactly what I was looking for: A well-tested stepper functionality that I can design however I want to. It consists of a CdkStep
used to manage the state of each step in the stepper and the CdkStepper
, which contains the steps (CdkStep
) and primarily handles which step is active.
Getting Started
It is straightforward to add the CDK to your Angular project:
Or alternatively for Yarn
:
You also need to add the CdkStepperModule
to your Angular module:
Demo Stepper Project
As the official documentation does not provide any code examples, I created a simple demo project on Stackblitz which I want to describe in the following sections.
Create CustomStepperComponent
The first step was to create a new Angular component for the CdkStepper
to be able to modify it. Therefore, the component needs to extend from CdkStepper
. The following example is a minimal implementation of a custom CDK stepper component:
The HTML template for this basic component:
We can now use our new CustomStepperComponent
in another component:
You must wrap each step inside a <cdk-step>
tag. For multiple steps, you can of course, use *ngFor
and use your custom step component inside:
Linear Mode
The above example allowed the user to navigate between all steps freely. The CdkStepper
additionally provides the linear mode, which requires the user to complete previous steps before proceeding.
You can either use a single form for the entire stepper or a form for each step to validate if a step is completed. Alternatively, you can pass the completed
property to each step and set the property value depending on your logic without using a form.
A simple example without using forms could look this way:
The steps are marked as editable="false"
which means that the user cannot return to this step once it has been marked as completed. It is impossible to navigate to the second step until the first one has been completed by clicking the Complete Step
button.
If you are then on step 2 it is impossible to navigate back to step 1.
Conclusion
I am pleased with the CdkStepper,
and it provided all the functionality I needed to refactor my legacy component. It was not necessary to write tests for this logic, and it automatically includes keyboard interaction support and cares about accessibility.
My advice is: If you ever need to implement a common behavior or component logic for your Angular application, please first look at the Angular Material CDK or similar libraries. Do not implement them yourself, as you will never get the same level of quality as from a maintained, widely-used open-source project like Angular Material.
The Engineering Behind My Portfolio Website
I created my first personal website in 2017 when I launched my first smartphone game. I use Google Analytics in this game, and it is, therefore necessary to provide a link to a privacy policy website from inside the game. I used WordPress and a free theme as I had nearly no frontend knowledge at that time:
Why I Switched From Visual Studio Code to JetBrains WebStorm (IntelliJ)
As I started my first JavaScript project in 2015, I used JetBrains WebStorm, which is an IDE (integrated development environment) for JavaScript development. I was already used to JetBrains IDEs as I worked before with Android Studio, which is based on IntelliJ IDEA. Additionally, I got a WebStorm license from my company and could use it without any restrictions.