ionic4-auto-complete
Index
About
This is a component based on Ionic's search-bar component, with the addition of auto-complete ability. This component is super simple and light-weight. Just provide the data, and let the fun begin. This package is compatible with Angular 2+ and Ionic 2+.
Setup
For Angular 2-7:
npm install ionic4-auto-complete@1.9.0 --save
For Angular 8+:
npm install ionic4-auto-complete --save
Add the following to the assets
array in angular.json
:
{
"glob": "**/*",
"input": "node_modules/ionic4-auto-complete/assets/",
"output": "./assets/"
}
Import AutoCompleteModule
by adding the following to your parent module (i.e. app.module.ts
):
import { AutoCompleteModule } from 'ionic4-auto-complete';
...
@NgModule({
...
imports: [
AutoCompleteModule,
...
],
...
})
export class AppModule {}
-
Add styles
-
Import scss stylesheet from node_modules
(i.e. app.scss
, global.scss
):
@import "../../node_modules/ionic4-auto-complete/auto-complete";
-
Create provider
-
Option One: Simple function returning an array
import {Component} from '@angular/core';
@Component({
selector: 'auto-complete-component',
templateUrl: 'auto-complete-component.component.html',
styleUrls: [
'auto-complete-component.component.scss'
],
})
export class AutoCompleteComponent {
public labelAttribute:string;
public objects:any[];
constructor() {
const objects = [
...
]
}
protected filter(keyword) {
keyword = keyword.toLowerCase();
return this.objects.filter(
(object) => {
const value = object[this.labelAttribute].toLowerCase();
return value.includes(keyword);
}
);
}
}
-
Option Two: Create a Service and Component
import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {map} from 'rxjs/operators';
import {Observable, of} from 'rxjs';
import {AutoCompleteService} from 'ionic4-auto-complete';
@Injectable()
export class SimpleService implements AutoCompleteService {
labelAttribute = 'name';
private countries:any[] = [];
constructor(private http:HttpClient) {
}
getResults(keyword:string):Observable<any[]> {
let observable:Observable<any>;
if (this.countries.length === 0) {
observable = this.http.get('https://restcountries.eu/rest/v2/all');
} else {
observable = of(this.countries);
}
return observable.pipe(
map(
(result) => {
return result.filter(
(item) => {
return item.name.toLowerCase().startsWith(
keyword.toLowerCase()
);
}
);
}
)
);
}
}
-
Option Three: Create a service and component with a form
-
To indicate that you don't want the label as value but another field of the country object returned by the REST service, you can specify the attribute formValueAttribute on your dataProvider. For example, we want to use the country numeric code as value and still use the country name as label.
-
Create a service which includes the formValueAttribute
property.
import {Injectable} from '@angular/core';
import {map} from 'rxjs/operators';
import {HttpClient} from '@angular/common/http';
import {AutoCompleteService} from 'ionic4-auto-complete';
@Injectable()
export class CompleteTestService implements AutoCompleteService {
labelAttribute = 'name';
formValueAttribute = 'numericCode';
constructor(private http:HttpClient) {
}
getResults(keyword:string) {
if (!keyword) { return false; }
return this.http.get('https://restcountries.eu/rest/v2/name/' + keyword).pipe(map(
(result: any[]) => {
return result.filter(
(item) => {
return item.name.toLowerCase().startsWith(
keyword.toLowerCase()
);
}
);
}
));
}
}
- Once the form is submitted the
country
is the selected country's numericCode while the displayed name is the labelAttribute
.
-
Create a component:
import {Component} from '@angular/core';
import {NavController} from 'ionic-angular';
import {CompleteTestService} from '../../providers/CompleteTestService';
import {FormGroup, Validators, FormControl } from '@angular/forms'
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
myForm: FormGroup
constructor(public navCtrl: NavController, public completeTestService: CompleteTestService) {
}
ngOnInit(): void {
this.myForm = new FormGroup({
country: new FormControl('', [
Validators.required
])
})
}
submit(): void {
let country = this.myForm.value.country
}
}
-
HTML
Documentation
-
Events
autoFocus($event)
is fired when the input is focused.autoBlur($event)
is fired when the input is blured.ionAutoInput($event)
is fired when user inputs.itemChanged($event)
is fired when the selection changes (clicked).itemsHidden($event)
is fired when items are hidden.itemRemoved($event)
is fired when item is removed (clicked).itemSelected($event)
is fired when item is selected from suggestions (clicked).itemsShown($event)
is fired when items are shown.
-
Searchbar Options
-
Ionic4-auto-complete supports the regular Ionic's Searchbar properties, which are set to their default values as specified in the docs.
-
You can override these default values by adding the [options]
attribute to the <ion-auto-complete>
tag, for instance:
<ion-auto-complete [dataProvider]="someProvider" [options]="{ placeholder : 'Lorem Ipsum' }"></ion-auto-complete>
-
Options include, but not limited to:
color
- (default is null
)debounce
- (default is 250
)type
- ("text", "password", "email", "number", "search", "tel", "url". Default "search".)placeholder
- (default "Search")
-
Styling
-
Resize
-
Custom Templates
-
Component Options
-
Searchbar Methods
-
Access Searchbar
-
Within your component:
@ViewChild('searchbar')
searchbar: AutoCompleteComponent;
-
Add #searchbar
within your component's HTML:
<ion-auto-complete [dataProvider]="provider" #searchbar></ion-auto-complete>
-
Available Methods
getValue()
returns the string value of the selected item.
- Example:
this.searchbar.getValue()
getSelection()
returns the selected object.
- Example:
this.searchbar.getSelection()
setFocus()
sets focus on the searchbar.
- Example:
this.searchbar.setFocus()
Contributing
To contribute, clone the repo. Then, run npm install
to get the packages needed for the library to work. Running gulp
will run a series of tasks that builds the files in /src
into /dist
. Replace the /dist
into whatever Ionic application's node_modules
where you're testing your changes to continuously improve the library.
Issues
If you find any issues feel free to open a request in the Issues tab. If I have the time I will try to solve any issues but cannot make any guarantees. Feel free to contribute yourself.
Demo
Run npm install
to get packages required for the demo and then run ionic serve
to run locally.
Thanks
Deploy
-
Generate Docs
-
Update Version
-
Build
- Run
npm run build
from root.
-
Test
- Copy
dist/
contents into demo/node_modules/ionic4-auto-complete/
- Run from root:
cp -fr dist/* demo/node_modules/ionic4-auto-complete/
- Run
ionic serve
from demo/
- Run
ionic build --prod
from demo/
-
NPM Release
- Run
npm publish
from dist/
directory.
-
Update Changelog
- Add updates to
CHANGELOG.md
in root.
Future Plans
- Add max and minimum options (for multi)
FAQ
-
How do you concatenate several fields as label?
The auto-complete component allows you to use templates for customize the display of each suggestion. But in many cases, the default template is good. However, you need to concatenate several fields (like firstname and lastname) to produce a full label. In that case, you can declare a method named getItemLabel
instead of using labelAttribute
.
For example, we want to display the country name and the population:
import {AutoCompleteService} from 'ionic4-auto-complete';
import {HttpClient} from '@angular/common/http';
import {Injectable} from "@angular/core";
import 'rxjs/add/operator/map'
@Injectable()
export class CompleteTestService implements AutoCompleteService {
formValueAttribute = ""
constructor(private http:HttpClient) {
}
getResults(keyword:string) {
return this.http.get("https://restcountries.eu/rest/v1/name/"+keyword)
.map(
result =>
{
return result.json()
.filter(item => item.name.toLowerCase().startsWith(keyword.toLowerCase()) )
});
}
getItemLabel(country: any) {
return country.name + ' (' + country.population + ')'
}
}