Angular CDK Keyboard List Navigation and Selection

Scenario

We have a Product item list and we want users to be able to navigate through it using the keyboard, perform typeahead searches, and select an active item.

Approach

Angular CDK uses a ListKeyManager instance to manage the active option in a list of items based on keyboard interaction.

For this use case we will be using the ActiveDescendantKeyManager which is one of the two varieties of ListKeyManager s that Angular CDK provides.

Setup

Create a new Angular Stackblitz and add @angular/cdk to the dependencies.

For styling we will use Materialize and so the CDN link needs to go in index.html .

<linkrel="stylesheet"href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/css/materialize.min.css"integrity="sha512-17AHGe9uFHHt+QaRYieK7bTdMMHBMi8PeWG99Mf/xEcfBLDCn0Gze8Xcx1KoSZxDnv+KnCC+os/vuQ7jrF/nkw=="crossorigin="anonymous"referrerpolicy="no-referrer"/>

Product Component

Create src/components/product.component.ts .

Each Product component instance will be an option for the ActiveDescendantKeyManager and therefore it needs to implement the ListKeyManagerOption interface.

interface ListKeyManagerOption {
disabled?: boolean;
getLabel?(): string;
}

Since we are using the ActiveDescendantKeyManager it also needs to implement the interface Highlightable .

interface Highlightable extends ListKeyManagerOption {
setActiveStyles(): void;
setInactiveStyles(): void;
}

This is our implementation.

Application Component

The application component will render our search field and the keyboard navigable list of products.

In order to initialize the ActiveDescendantKeyManager instance we need to do three things.

  • Create a @ViewChildren query for selecting the ProductComponent instances being used as options.
  • Initialize the ActiveDescendantKeyManager with the options.
  • Forward keyboard events from the application component to the ActiveDescendantKeyManager.

This is our app.component.ts implementation.

Within ngAfterViewInit we initialize the ActiveDescendantKeyManager calling withWrap , which causes the list to wrap when the keyboard navigation gets tot the end, and withTypeAhead which allows us to select specific items in the list via the search field.

Our application component template binds the onKeyUp method which performs navigation by forwarding non ENTER events to the keyManager . ENTER events cause the selection field to be set with the current selection.

The filter pipe implementation that we are delegating product selection to when the user queries is implemented as follows.

Demo

Selecting the search field and try typing in the name of a product. Navigate using the arrow keys. Enter will select the currently active item.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Ole Ersoy

Ole Ersoy

Founder of Firefly Semantics Corporation