What are some ways to optimize the performance of a Select Box?

I am attempting to show a lengthy list of countries in an ion-select. Currently, there are 249 countries that I need to load. Unfortunately, the rendering performance is quite slow on my phone.

<ion-list margin-top margin-bottom>
    <ion-item>
      <ion-label margin-left style="color:#3498db">Country</ion-label>
      <ion-select margin-right [(ngModel)]="country" okText="Done" placeholder="Select">
        <ion-option *ngFor="let item of countries" [value]="item.ccode" [selected]="country == item.ccode">{{item.cname}}</ion-option>
      </ion-select>
    </ion-item>
  </ion-list>

Is there a way to enhance the rendering performance?

Answer №1

To efficiently achieve this, implementing a Modal is the recommended approach. Additionally, including a search bar at the top can assist users in easily locating their desired country. The provided example serves as a simplified demonstration (please inform me of any identified errors, as extraneous code has been omitted).

It should be noted that instead of utilizing an ion-list with individual ion-item components per country, standard div elements are being used in the view. This decision was made due to the substantial number of countries (~250), necessitating the initialization, rendering, and creation/destruction of Ionic components each time the list is filtered. In the demo, performance remains optimal even on older mobile devices by using basic HTML elements with minimal styling rules.

Controller

// Angular
import { Component } from '@angular/core';

// Ionic
import { NavParams, ViewController } from 'ionic-angular'; 

@Component({ 
    selector: 'page-country-list', 
    templateUrl: 'country-list.html' 
    })
export class CountryListPage {

    public countries: Array<any>;
    public countriesToShow: Array<any>;

    constructor(private paramsCtrl: NavParams, private viewCtrl: ViewController) {
        // Retrieve data passed as a parameter
        this.countries = paramsCtrl.get('countries');

        // Initialize the list of countries to display in the view
        this.initializeCountriesToShow();
    }

    public initializeCountriesToShow(): void {
        // Make a clone of the country list to avoid modifying the original copy
        this.countriesToShow = [...this.countries];
    }

    public filterCountries(ev: any): void {
        // Reset the displayed countries to show all
        this.initializeCountriesToShow();

        // Get the value from the searchbar
        let val = ev.target.value;

        // If the value is empty, do not filter the countries
        if (val && val.trim() != '') {
            this.countriesToShow = this.countriesToShow.filter((country) => {
                return (country.name.toLowerCase().indexOf(val.toLowerCase()) > -1);
            })
        }
    }

    // Return the selected country to the caller
    public selectCountry(country: any): void {
        this.viewCtrl.dismiss(country);
    }

    // Close the modal without returning anything
    public close(): void {
        this.viewCtrl.dismiss();
    }
}

View

<ion-header>
    <ion-navbar color="primary">
        <ion-title>Countries</ion-title>
        <ion-buttons right>
            <button (click)="close()" ion-button icon-only>
                <ion-icon color="light" class="close-icon" name="close"></ion-icon>
            </button>
        </ion-buttons>
    </ion-navbar>
    <ion-toolbar color="primary">
        <ion-searchbar placeholder="Type the name here..." (ionInput)="filterCountries($event)"></ion-searchbar>
    </ion-toolbar>
</ion-header>
<ion-content padding>
    <div class="country-list">
        <div tappable (click)="selectCountry(country)" class="country-item" *ngFor="let country of countriesToShow">
            {{ country.name }}
        </div>
    </div>
</ion-content>

Styles

.ios, .md {
    page-country-list {

        div.country-item {
            position: relative;
            margin-right: 16px;
            margin-left: 16px;
            margin-top: 16px;
            padding-bottom: 16px;
            border-bottom: 0.55px solid map-get($colors, light);

            &:last-child {
                border-bottom: none;
            }
        }

        ion-navbar {
            .close-icon {
                font-size: 3.5rem;
                padding-right: 8px;
            }
        }

    }
}

Caller component

To display the modal, you can follow this procedure:

constructor(private modalController: ModalController) {}

// ...

public showCountryDropdown(): void {

    // Create the modal
    let modal = this.modalCtrl.create('CountryListPage');

    // Manage the returned result
    modal.onDidDismiss(country => {
        if (country) {
            // Process the selected country
            // ...
        }
    });

    // Show the modal
    modal.present();
}

Note: The assumption made in the demo is that each country object includes a name property.

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

The specified 'Object' type does not match the required 'Document' constraint

I need assistance with running a MERN application to check for any issues, but I keep encountering this error across multiple files. Error: The 'CatalogType' type does not meet the requirements of 'Document'. The 'CatalogType&apo ...

Using Generic Types in Response DTO with Typescript, NestJs, and Class Transformer

In my project, I am dealing with multiple endpoints that provide responses along with pagination details. My goal is to have a single parent type for the pagination and be able to use different data types for the data parameter. I attempted the following ...

The JQuery signature does not include the necessary string context

We are in the process of transitioning legacy JavaScript code to TypeScript. In our current codebase, we have jQuery selectors that utilize a string as a context: $("example", "someId"). However, when converting this to TypeScript, the definition file JQu ...

What steps are required to configure angular-eslint for a protractor project?

I am in the process of transitioning to eslint using angular-eslint due to TSLint being deprecated. While going through the documentation, I noticed that there is no mention of protractor. My question is, can the default .eslintrc.json configuration be use ...

Utilizing classes as types in TypeScript

Why is it possible to use a class as a type in TypeScript, like word: Word in the provided code snippet? class Dict { private words: Words = {}; // I am curious about this specific line add(word: Word) { if (!this.words[word.term]) { this.wor ...

Calling a typed function with conditional types in Typescript from within another function

In my attempt to create a conditional-type function, I stumbled upon this question on Stack Overflow. Unfortunately, it seems that the approach doesn't work well with default values (regardless of where the default value is placed). Following the advi ...

The use of URL embedded parameters in @angular/http

Currently, I am utilizing a backend system that accepts search query parameters in both the ?-notation and the url-embedded format. I understand that I can use tools like URLSearchParams/RequestOptionsArgs to send requests to . However, I am curious about ...

There has been an unhandled runtime error: [object ProgressEvent] occurring with Next.js/Typescript

Exploring the world of nextJS and typescript is new to me. I am currently working on creating a simple blog using nextJS/typescript with a sanity CMS backend. Everything seems to be running smoothly during development, but then I encounter this Unhandled R ...

What is the best way to invoke a function using a string as its name?

In my grid configuration function, I am assigning column definitions. One key, valueGetter, requires a function to be called to fetch the column value. The issue I am encountering is that the API returns this value as a string. When I try to set it using ...

Modal for Firestore CRUD operations update()

Currently seeking assistance with a CRUD system that involves modal dialogues. I have successfully implemented adding and deleting functionalities, but I am encountering an issue with editing. Although I can retrieve the data for each record in its respect ...

Is it possible for Angular Components to be dynamically generated based on a parameter?

Is it feasible to achieve the following functionality in Angular? I am interested in creating multiple components that share a common base interface of properties; for instance, a string component, a date component, and an integer component, each with uni ...

AG-Grid hierarchical data structure

Transitioning from kendo tree list to ag grid tree data grid, I am facing a challenge. My table data is currently formatted as shown below, but ag grid requires data in the form of a string array of nodes in a tree. How can I adapt or customize my existing ...

Creating a Typescript mixin function that accepts a generic type from the main class

I am working with the code snippet shown below: // Types found on https://stackoverflow.com/a/55468194 type Constructor<T = {}> = new (...args: any[]) => T; /* turns A | B | C into A & B & C */ type UnionToIntersection<U> = (U extend ...

Guide on positioning a span element to the left using the margin auto property in CSS for Angular 4

Having trouble with moving numbers highlighted to the left with names in CSS. I've tried using flex direction and margin auto but can't achieve the desired result. https://i.sstatic.net/kRJOb.png Here is my HTML code: <section class="favorit ...

Visual Studio Code's Intellisense is capable of detecting overloaded functions in JavaScript

What is the best way to create a JavaScript overload function that can be recognized by Visual Studio Code IntelliSense, and how can this be properly documented? A good example to reference is Jasmine's it() function shown below: function it(expecta ...

Guide on Combine Multiple Observables/Subscriptions into a Nest

1. A Puzzle to Solve I am faced with the challenge of implementing a dynamic language change flow for my blog. Here is an overview of how I envision it: The user initiates a language change by clicking a button that triggers an event (Subject). This eve ...

What is the best way to implement animation effects in Angular?

I am currently working on developing an application with Angular animations for a span. After studying the example provided in this StackBlitz Example, I attempted to implement my own animated span. To showcase my progress, I have created a MyStackBlitz. ...

Storing multiple strings in a string array in Angular2

Hi everyone, I’m just getting started with Angular and currently working on creating a recipe page that fetches data from an API. The API setup is complete, but now I need to figure out how to input the data into the API using Angular. I have defined a ...

Make sure to confirm that 'tables-basic' is an Angular component within the module before proceeding

In my table-basic.component.ts file, I declared 'tables-basic' as a selector and included this template in dashboard.html. Despite following the steps outlined below, I encountered an error which is also highlighted. Snippet from my dashboard.te ...

Tips for showing a DialogBox when a blur event occurs and avoiding the re-firing of onBlur when using the DialogBox

Using React and Material UI: In the code snippet provided below, there is a table with TextFields in one of its columns. When a TextField triggers an onBlur/focusOut event, it calls the validateItem() method that sends a server request to validate the ite ...