Scrolling through a list in Angular using cdk-virtual-scroll-viewport while selecting items via keyboard input

Looking to implement a customized Autocomplete feature.

As the user begins typing, a small window should appear with selectable options. I want users to have the ability to navigate and select an option using their keyboard.

For instance: - User types "Hou" - Available options are shown as ["House", "Houston"] - User presses the down arrow key on the keyboard and then hits enter to choose "house"

This is my custom scroll component for the pop-up:

<ul class="plDropdown-optionList">
          <cdk-virtual-scroll-viewport style="height: 200px" itemSize="30">
            <ng-container *cdkVirtualFor="let option of displayableOptions">
              <button class="plDropdown-option" type="button" (click)="selectOption(option)">
                {{option}}
              </button>
            </ng-container>
          </cdk-virtual-scroll-viewport>
        </ul>

Answer №1

For those seeking a solution, here is an option that might help.

I implemented a keyboard event using the Input tag:

<input (keydown)="processInput($event)">

This function determines the key pressed:

processInput(evt: KeyboardEvent): void

It keeps track of the selected reference and updates it accordingly:

private _updateIndex(key: string): void {
    switch (key) {
      case Key.ArrowUp:
        if (this.selectedIndex === 0) {
          return;
        }

        this._setIndex(this.selectedIndex -= 1);
        break;

      case Key.ArrowDown:
        this.displayedTags$
        .pipe(
          take(1)
        )
          .subscribe((results) => {
            if (this.selectedIndex >= results.length - 1) {
              this._setIndex(results.length - 1);

              return;
            }

            this._setIndex(this.selectedIndex += 1);
          });
        break;

      default:
        break;
    }
  }

  private _selectIndex(): void {
    this.displayedTags$.pipe(
      take(1)
    )
    .subscribe((results) => {
      const result = results[this.selectedIndex];

      if (result) {
        this.selectResult(result);
      }
    });
  }

  private _setIndex(index: number): void {
    this.selectedIndex = index;
  }

To highlight the current line in your HTML file, include this code snippet:

[ngClass]="{'focus-background': selectedIndex == idx}"

Your HTML will now look like this:

 <cdk-virtual-scroll-viewport style="height: 400px" itemSize="30">
            <ng-container *cdkVirtualFor="let option of displayedTags$ | async; index as idx" (isSelected)="true">
              <button class="plTagsComponent-option" type="button" (click)="selectResult(option)" (isSelected)="true"
                [ngClass]="{'focus-background': selectedIndex == idx}" (mouseenter)="onHover(idx) ">
                {{option.label}}
              </button>
            </ng-container>
          </cdk-virtual-scroll-viewport>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Having trouble with the API authentication call, receiving a "Failed to load resource: net::ERR_CONNECTION_REFUSED" error message

I am facing an issue with my Vue and .net application. Whenever I run "NPM start serve," it successfully builds the app. The app is running locally at: http://localhost:8080/ However, when I attempt to log in, I encounter the following error: Console err ...

Implementing Observable in NativeScript with TypeScript - A Step-by-Step Guide

Recently, I delved into the world of native-script framework and decided to dive into the "Get Started with JavaScript" tutorial provided on their official website. My background in Java has made me more comfortable with typescript, so I attempted to swap ...

Issues with integrating Angular Cypress Component tests with Tailwindcss are causing problems

While implementing Tailwindcss in an Nx style monorepo structure with 'apps' and 'libs' folders, I configured the Tailwind file as follows: content: ['./apps/**/*.{html,ts}', './libs/**/*.{html,ts}'], However, despi ...

Load data into data tables through AJAX request

I'm currently working on implementing datatables and I'm facing an issue with populating my data table using an AJAX call. Here is the snippet of my AJAX call: $('#call_analysis_basic_table').DataTable ({ "ajax": { "url": " ...

Creating a fantastic Image Gallery in JavaScript

As I work on creating a basic gallery page with html and css, everything seemed to be running smoothly. However, upon testing it in Google Chrome and IE, the onmouseover function is not responding as expected. The idea is for a larger image to display in t ...

A guide to using jqGrid: Retrieve the value of a particular cell by double clicking on a row

Is there a way to implement a feature where users can double click on any part of a row and have it open a new HTML page based on the specific content in a cell? For example, I have a table with different counties in New York listed in separate rows: Coun ...

Navigating back to previous page with the help of Authguard

I am looking to incorporate a redirection feature where, if a user is logged in, they should be directed to the previous page. For example, from Page A to Login (successful) back to PageA. I have tried using the router event subscribe method for this purpo ...

Guide to making a TreeView in Angular 2 with Typescript

How can I implement a TreeView in Angular 2 using Typescript? I have searched on Google but have not found any working examples, etc. Could someone kindly provide me with an example to help me accomplish this task? ...

Using Next.JS useRouter to access a dynamic route will result in receiving an empty object as the return value

I've encountered an issue with dynamic routing in my specialized calendar application built with Next.JS. One of my pages is working perfectly fine while the other is not functioning at all. The first page (working): // pages/date/[year]/[month]/[day ...

What is the best way to eliminate the # symbol in angular 5 URLs?

Currently, I am working on a project in Angular 5 and I need to remove the hash symbol (#) from my URL. The current URL looks like this: http://localhost:4200/#/product/add. While it works fine after being published on my domain, I encounter a 404 error ...

Navigate to a specific URL path and send properties as arguments in the function for handling events

I am working on a vuetify autocomplete search feature. When a user selects an item, I need to navigate to a specific route and pass some props along. However, my attempts to change the current route without passing props have resulted in errors. Here is w ...

Angular 2 and 4 now have a specialized node module designed to create tree-like structures within the framework

Are there any node packages available for creating tree-like structures in Angular 2 or 4, similar to what is shown here ? I am looking for the ability to customize templates within the tree. Any suggestions? ...

Displaying dates on the Amcharts category axis for instances with empty data

I am currently creating a fruit consumption chart for each day, and so far everything is working correctly in the provided example. var chart = AmCharts.makeChart("chartdiv", { "type": "serial", "hideCredits": true, "fixedColumnWidth": '10px& ...

suspicion arises that the argument is not correctly referencing the appropriate variables

I am trying to grasp the situation happening here. I have two variables activeToInactive and inactiveToActive which I increase whenever a status is updated. Here's my code snippet: Counter Service: export class CounterService { // Initial States ...

``motioning a component beneath another component that may be in a state

Having an issue with my CSS. I have some elements generated by JavaScript and when hovering over them, another element is displayed below the others for some reason. Here's the CSS related to this problem: .hiddenTextjob { display:none; ...

Encountering a Spring Boot 404 error when deploying static content as a jar file

Utilizing a Spring Boot application alongside an Angular JS project housed in separate modules raises some concerns. The Angular JS files, located within the 'dist' folder, have been converted into jar files and integrated into the Spring Boot se ...

Guide to easily printing a page in Angular 4 using TypeScript

When using my web app, there are certain pages where I need to print only a specific component without including the sidebar. I have written the following TypeScript code to achieve this: print() { window.print(); } The relevant HTML code begins with: & ...

IIFE and the Twitter share button are a powerful duo

As I experiment with this quick creation of mine, two questions have arisen. The first one is, how can I encapsulate all the JS code within an IIFE without breaking it? The second question is about finishing the twitter button to enable sharing the act ...

The confirmPasswordReset function in Angularfire auth is not defined in the User type

I am currently working on integrating password reset functionality using the angularfire2/auth class, following the steps outlined in this guide: https://medium.com/@c_innovative/implementing-password-reset-can-be-a-tricky-but-inevitable-task-737badfb7bab ...

What is the proper way to delete a callback from a promise object created by $q.defer() in AngularJS?

When working with AngularJS, the $q.defer() promise object has the ability to receive multiple notify callbacks without overwriting previous ones. var def = $q.defer(); def.promise.then(null, null, callback1); def.promise.then(null, null, callback2); If ...