How to implement Ionic autocomplete

In this article, we’ll how to implement ionic autocomplete using the ng-select plugin. The ng-select plugin is typeahead and improves user experience by supplying all possible lists of choices based on text user type in the input field.

The ng-select is a flexible autocomplete/typeahead/suggestion component that can use in angular and ionic applications. The ng-select is a lightweight all-in-one UI Select, Multiselect, and autocomplete component. In this example, we will create two examples of Ionic autocomplete.

  1. Single typeahead using custom typeahead service for Ionic autocomplete.
  2. Multiselect typeahead for Ionic autocompletes search.

In this tutorial, we will learn how to implement autocomplete or typeahead in our ionic application. We have plenty of other libraries to use but in this example, we are using the ng-select library to implement autocomplete.

Prerequisites:
To create and run an Ionic project, We need nodejs and Ionic CLI already install in our system, if not then check how to install nodejs and Ionic in Ubuntu. Ionic CLI allows us to create an Ionic project, generate application and library code, and perform a variety of ongoing development tasks such as testing, bundling, and deployment. To install the Ionic CLI, open a terminal, and run the following command:

npm install -g @ionic/cli

Setting up and configure the project for Ionic autocomplete search

With the release of ionic version 4, the Ionic framework is no longer limited to angular, we can create the ionic projects in different front-end frameworks like Angular, Vue, and React. Let first create a blank Ionic Angular project for Ionic autocomplete and install the ng-select library.

$ionic start ng-select blank --type=angular
npm i @ng-select/ng-select --save
ionic autocomplete search
Ionic autocomplete search

Example of Ionic auto-complete Apps

We need to import the ng-select module on our page, in our case we are using the home.module.ts file of ionic. An import NgSelectModule module on our page and we are also importing ReactiveFormsModule in our home. module.ts this file as we are using the form.

import { NgModule } from '@angular/core';
...
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { NgSelectModule } from '@ng-select/ng-select';
import { HomePage } from './home.page';

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    ReactiveFormsModule,
    IonicModule,
    RouterModule.forChild([
      {
        path: '',
        component: HomePage
      }
    ]),
    NgSelectModule
  ],
  declarations: [HomePage]
})
export class HomePageModule {}

We will create dummy data states.json containing a few US state names, create folder data, and create a new file states.json. Add following few state names in assets/data/states.JSON as

{
    "states": [
        { "name": "Alabama" },
        { "name": "Alaska" },
        { "name": "Arizona" },
        { "name": "Arkansas" },
        { "name": "California" },
        { "name": "Colorado" },
        { "name": "Connecticut" },
        { "name": "Delaware" },
        { "name": "Florida" },
        { "name": "Georgia" },
        { "name": "Hawaii" },
        { "name": "Idaho" }
    ]
}

The ng-select component with your options and we can also loop the loop. Add the following code of typeahead input in our template, home.page.html

<ion-header [translucent]="true">
  <ion-toolbar color="primary">
    <ion-title>
      Ionic autocomplete | multiselect | typeahead
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true">
  <div class="ion-padding">
    <form [formGroup]="form">
      <ion-label>Select State</ion-label>
      <ng-select [items]="states | async" bindLabel="name" formControlName="name" notFoundText="No records found"
        (keyup)="getStatesName($event)">
      </ng-select>
    </form>

    <div class="multiSelect">
      <label>Multiselect with custom bindings</label>
      <ng-select [items]="cities2" bindLabel="name" bindValue="name" [multiple]="true" placeholder="Select cities"
        [(ngModel)]="selectedCityNames">
      </ng-select>
      <p>
        Selected cities: {{selectedCityNames}}
      </p>
      <hr />
    </div>
  </div>
</ion-content>

Add the following code of typeahead input in our template, home.page.ts file

mBuilder.group({
import { Component } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Observable } from 'rxjs';
import { TypeaheadService } from '../services/typeahead.service';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage {
  form: FormGroup;
  states: Observable<string[]>;
  selectedCityNames: string[];
  cities2 = [
    { id: 1, name: 'Vilnius' },
    { id: 2, name: 'Kaunas' },
    { id: 3, name: 'Pavilnys', disabled: true },
    { id: 4, name: 'Pabradė' },
    { id: 5, name: 'Klaipėda' }
  ];

  constructor(private formBuilder: FormBuilder, private typeahead: TypeaheadService) {
    this.createForm();
  }

  createForm() {
    this.form = this.formBuilder.group({
      name: [],
    });
  }

  getStatesName(event) {
    this.states = this.typeahead.getStates(event.target.value);
  }
}

Styling Ionic autocomplete input design

To allow customization and theming of Ionic autocomplete, ng-select the bundle includes only generic styles that are necessary for correct layout and positioning. To get a full look at the control, include one of the themes in your application.

@import "[email protected]/ng-select/themes/default.theme.css";
// ... or  
@import "[email protected]/ng-select/themes/material.theme.css";

Import one of the above themes for our ionic autocomplete in our global.scss file in our project.

@import "[email protected]/ng-select/themes/default.theme.css";

Ionic autocomplete using common autocomplete service

When we have more than one component using Ionic autocomplete then we can use a common service for all Ionic autocomplete. This will reduce our code and easy to manage our code. Let’s first create a custom common service for Ionic autocomplete, so we can share it among different components in our project.

ionic generate service services/typeahead


Add the following code in our custom typeahead.service.ts

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class TypeaheadService {

  constructor(private http: HttpClient) { }

  getStates(term: string = null): Observable<string[]> {
    return new Observable((observer) => {
      let getStatesNamePromise: Promise<any>;

      getStatesNamePromise = new Promise((resolve) => {
        this.http.get<string[]>('./assets/data/states.json').subscribe((data: any) => {
          resolve(data.states);
        });
      });

      getStatesNamePromise.then((data) => {
        if (term) {
          data = data.filter(x => x.name.toLocaleLowerCase().indexOf(term.toLocaleLowerCase()) > -1);
        }
        observer.next(data);
      });
    });
  }
}

On the consumer page, we have to inject our typeahead service in the constructor and add the following code to get typeahead in our home.page.ts file

constructor(... private typeahead: TypeaheadService) {}

  getStatesName(event) {
    this.states = this.typeahead.getStates(event.target.value);
  }

In the template, we need to subscribe our observable using async  

    <form [formGroup]="form">
      <ion-label>Select State</ion-label>
      <ng-select [items]="states | async" bindLabel="name" formControlName="name" notFoundText="No records found"
        (keyup)="getStatesName($event)">
      </ng-select>
    </form>

Ionic autocomplete with image and ng-option loop

The ng-select component also has an ng-option sub-component which allows us to loop through our sources array. In ng-option, we can include images and other text content. Here’s a quick gif animation of Ionic autocomplete with an image of what we’ll be building.

ionic autocomplete search
ionic autocomplete search

We need dummy data for our Ionic to autocomplete image and create a file called countries.json and add the following data.

[
    {
      "name": "Russia",
      "flag": "f/f3/Flag_of_Russia.svg",
      "area": 17075200,
      "population": 146989754
    },
    {
      "name": "France",
      "flag": "c/c3/Flag_of_France.svg",
      "area": 640679,
      "population": 64979548
    },
    {
      "name": "Germany",
      "flag": "b/ba/Flag_of_Germany.svg",
      "area": 357114,
      "population": 82114224
    },
    {
      "name": "Canada",
      "flag": "c/cf/Flag_of_Canada.svg",
      "area": 9976140,
      "population": 36624199
    },
    {
      "name": "Vietnam",
      "flag": "2/21/Flag_of_Vietnam.svg",
      "area": 331212,
      "population": 95540800
    },
    {
      "name": "Mexico",
      "flag": "f/fc/Flag_of_Mexico.svg",
      "area": 1964375,
      "population": 129163276
    },
    {
      "name": "United States",
      "flag": "a/a4/Flag_of_the_United_States.svg",
      "area": 9629091,
      "population": 324459463
    },
    {
      "name": "India",
      "flag": "4/41/Flag_of_India.svg",
      "area": 3287263,
      "population": 1324171354
    }
]

Edit home.page.ts file to retrieve our countries’ data from our dummy source using the HttpClient GET method.

import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit {
  form: FormGroup;
  countries: any[];
  selectedCountry: any;

  constructor(private formBuilder: FormBuilder, private http: HttpClient) {
    this.createForm();
  }

  ngOnInit(): void {
    this.http.get('./assets/data/countries.json').subscribe((data: any) => {
      this.countries = data;
    });
  }

  createForm() {
    this.form = this.formBuilder.group({
      name: [],
    });
  }
}

In our home.page.html template, we have our ng-select element with ng-option where we can add images and other text.

<ion-content [fullscreen]="true">
  <form class="ion-padding">
    <ng-select [(ngModel)]="selectedCountry">
      <ng-option *ngFor="let country of countries" [value]="country.id">
        <img [src]="'https://upload.wikimedia.org/wikipedia/commons/' + country.flag" class="mr-2" style="width: 20px">
        {{ country.name }} Population: {{ country.population | number }}
      </ng-option>
    </ng-select>
  </form>
</ion-content>

Conclusion
We have completed our Ionic autocomplete and multi-select on input using the ng-select library, there are many third-party libraries that achieve Ionic autocomplete. The ng-select is one of the most popular and lightweight all-in-one UI Select, Multiselect, and Autocomplete for Ionic and Angular.

Related posts


Spread the love

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top