Angular: Binding dropdown with huge data set
By: Coding In Depth
Tags: Angular, Performance, Autocomplete, Dropdown, Web Development

3. Any dropdown with Scroll

This is the basic math that many developers use to find the bottom of the scroll. So when you open dropdown use the dropdown height and total height of the component. Create start and end indexes based on the height and then create a callback to refresh the result. There are plenty of articles for this approach online. It is useful however less cleaner approach.

2. PrimeNG Autocomplete

PrimeNG provides very useful autocomplete module. Install PrimeNG dependencies to access PrimeNG autocomplete modules. PrimeNG autocomplete uses BrowserAnimationsModule. Include the dependency of BrowserAnimationsModule in the project.

import { BrowserAnimationsModule } from ‘@angular/platform-browser/animations’;

Import the AutoCompleteModule module in the root module.

import {AutoCompleteModule} from ‘primeng/autocomplete’;

Now PrimeNG dropdown is good to use. Specify which fields need to show in the dropdown. The completeMethod is the search method for the autocomplete.

<h5>PrimeNG Autocomplete</h5> <p-autoComplete [(ngModel)]=”text” [suggestions]=”results” field=”productName”(completeMethod)=”search($event)” placeholder=”Search product name” [forceSelection]=”true” [dropdown]=”true” ></p-autoComplete>

Now define search method search($event) in the component.

search(event) { console.log(event.query); this.productService.searchProducts(event.query).subscribe(data => { this.results = data; }); }

Since we do not have an actual API for the demo. Let’s generate a bunch of products say 30 for now and search auto-complete from these 30 products. Create a search method in product service which is of type of Product.

searchProducts(searchString: string): Observable<Product[]> { console.log(‘searchProducts’) let newList=[]; for (var _i = 0; _i < 30; _i++) { let newProduct: Product = { productName: “This Product #” + _i, prodid: _i } newList.push(newProduct); } if (!searchString && !searchString.trim()) return of(newList); else { let wholeProd = […newList]; let filterdProducts = wholeProd.filter(x => x.productName.toLowerCase().indexOf(searchString.toLowerCase()) > -1); console.log(filterdProducts); return of(filterdProducts); } }

The benefits of using PrimeNG autocomplete is that it is shipped with other controls. So if you are using other PrimeNG controls. Using autocomplete is the best option. Also, the package upgrade of PrimeNG is quite promising. The current version is fully compatible with the Angular 9.

1. NG-Select Autocomplete and Virtual Scroll

The ng-select comes with very exciting features. It provides both search as well as virtual scroll capability. It provides callback for virtual scrolling. This callback can be integrated with the API to take the remaining result from the API and concatenate with the existing result. Install and import the ng-select module in the root module.

import { NgSelectModule } from ‘@ng-select/ng-select’;

Now we can use the ng-select tag in the templates. We can define a binding label property from the array. Here we are showing the product name in the dropdown. Also need to set virtualScroll as true and clearable as false. The method scrollToEnd and searchProd is very important. It provide search as well as virtual scroll capabilities.

<ng-select [items]=”ngSelList” bindLabel=”productName” bindValue=”productName” placeholder=”Select item” [searchable]=”true” [clearable]=”false” [(ngModel)]=”selected” [virtualScroll]=”true” [loading]=”loader” (search)=”searchProd($event)” (scrollToEnd)=”scrollToEnd()” (open)=”openDropdown($event)” [ngModelOptions]=”{standalone: true}”> </ng-select>

Now we will create a create product method in the product service. This will serve as fake API calls. Creating a static counter which will keep increasing when the user scrolls to the bottom. Also, this method accepts IsConcat. Which is used in the scroll to append the results?

createProducts(IsConcat: boolean): Observable<Product[]> { var counter = ProductService.counter; console.log(`create Prod ${IsConcat} Counter is ${ counter }`); // public ngSelList = [‘Some Product 1’,’Some Product 1']; var newList = []; if (IsConcat) var newlength = IsConcat ? counter + 20 : 20; for (var _i = counter; _i < newlength; _i++) { let newProduct: Product = { productName: “This Product #” + _i, prodid: _i } newList.push(newProduct); } ProductService.counter = this.ngSelList.length; if (IsConcat) { this.ngSelList = this.ngSelList.concat(newList); } else this.ngSelList = newList; ProductService.counter = this.ngSelList.length; console.log(`Product list is ${this.ngSelList.length} and static counter is ${ProductService.counter}`); return of(this.ngSelList); }

In component, we can write three methods. First, we will pull some default products in ngOnInit. If openDropdown we keep adding 30 products in the initial 30 products. Similarly in scrollToEnd method, we keep adding 30 elements.

ngOnInit() { this.productService.createProducts(false).subscribe(resp => { this.ngSelList = resp; this.counter = this.ngSelList.length; }); } scrollToEnd() { console.log(‘scrollToEnd’); this.productService.createProducts(true).subscribe(resp => { this.ngSelList = resp; this.counter = this.ngSelList.length; }); } openDropdown(event: any) { console.log(‘openDropdown’); this.productService.createProducts(true).subscribe(resp => { this.ngSelList = resp; this.counter = this.ngSelList.length; }); }

Whoa! Now we can see the dropdown rendered and pulling 30 products in virtual scroll.

The benefit of using the ng-select is it provides a very cleaner approach to render a large data set. Also, they are proving regular updates with the Angular versions.

On the downside, If you are using PrimeNG or Angular Material UI themes. You have to decorate the ng-select component looks similar to PrimeNG or Angular Material UI themes.

Summary

We have discussed the traditional way of rendering Angular dropdown. We have also discussed how to render a dropdown using scroll, search, and on-demand strategy. We have implemented in detail using PrimeNG autocomplete and the NG-select dropdown. Check the stackblitz project to code more on these control. Attaching the GitHub link.