Accessibility Made Easy with Angular CDK

Netanel Basal
Netanel Basal
Published in
4 min readSep 19, 2018

--

Keyboard focus and navigation are essential when developing for the accessible web. Many users rely on a keyboard when they surf the web.

If a user doesn’t use other input mechanisms, they’ll have a tough time interacting and navigating your site unless it’s keyboard navigable.

In this article, we’ll learn how Angular CDK makes adding this ability easier.

We’ll create a searchable list and add the option to choose items using the keyboard. Here is a demo that illustrates our final result:

Let’s start by creating a list-item component:

This component is straightforward. It gets the item via input and displays the content via ng-content. Now, let’s move on and create the app component:

This is basic stuff. We loop over an array of users and display the username. Now we have a searchable list, so let’s add the keyboard interaction.

The ListKeyManager Class

ListKeyManager manages the active options in an item list based on keyboard interactions. It’s intended to be used with components that correspond to a role="menu” or role="listbox” pattern.

Any component that uses a ListKeyManager need to do three things:

  • Create a @ViewChildren query for the options being managed.
  • Initialize the ListKeyManager, passing in the options.
  • Forward keyboard events from the managed component to the ListKeyManager.

There are two varieties of ListKeyManager, ActiveDescendantKeyManager and FocusKeyManager. Let’s start with ActiveDescendantKeyManager .

The ActiveDescendantKeyManager Class

We instantiate the ActiveDescendantKeyManager class, which extends the ListKeyManager class and passes on the query list to it.

We also call the withWrap() method, as we want to wrap to the other end of the list when there are no more items in a given direction (looping).

We listen for the input’s keydown event and pass the event to the onKeyDown() method of the keyManager object. Under the hood, active option will be managed based on the user’s keyboard navigation.

When the user presses enter, we can grab the active option via the activeItem property of the keyManager object.

Now, let’s see how to style the active option. Each managed item should implement the Highlightable interface:

As the user navigates, Angular calls the setActiveStyles() method on the newly active option and setInActiveStyles() on the previously option. This allows us to style our component.

The FocusKeyManager Class

The FocusKeyManager class is used when options receive direct browser focus. Each managed item must implement the FocusableOption interface:

As the user navigates, Angular calls the focus() method on the newly active option.

Tab Focus

Skipping Items

We have two options for skipping items during navigation. The first option is setting the item disabled property to true. For example:

The second option is to define a skipPredicate() method. For example:

Typehead Mode

We can turn on the typeahead mode. This allows users to set the active item by typing. That means that when the user searches, the first result is automatically set as active.

Let’s add the search functionality.

Note that we must implement the getLabel() method when we’re in typehead mode.

And of course, in addition to all of that, you can dynamically set the active item by calling methods like: setFirstItemActive(), setLastItemActive(), updateActiveItem(index), setActiveItem(item) and more.

FocusTrap

There may come a time when you find it essential to trap focus within a DOM node — that way, when users hit Tab or Shift+Tab or click around, they can’t escape a certain cycle of focusable elements (this is useful for modals, for example).

The cdkTrapFocus directive traps Tab key focus within an element. Let’s see an example:

That’s all. Here are the complete examples:

ActiveDescendantKeyManager
FocusKeyManager

👂🏻 Last but Not Least, Have you Heard of Akita?

Akita is a state management pattern that we’ve developed here in Datorama. It’s been successfully used in a big data production environment for over seven months, and we’re continually adding features to it.

Akita encourages simplicity. It saves you the hassle of creating boilerplate code and offers powerful tools with a moderate learning curve, suitable for both experienced and inexperienced developers alike.

I highly recommend checking it out.

Follow me on Medium or Twitter to read more about Angular, Akita and JS!

--

--

A FrontEnd Tech Lead, blogger, and open source maintainer. The founder of ngneat, husband and father.