For this tutorial, we will continue from the previous tutorial. We will build an application that works to display currency conversions and exchange rates based on the selected country. An exchange rate is the rate at which one currency can be exchanged for another between nations or economic zones. It is used to determine the value of various currencies in relation to each other and is important in determining trade and capital flow dynamics.
We will use the free API from Exchangerate which is a simple and lightweight free service for current and historical foreign exchange rates & crypto exchange rates. For this tutorial we will use only the Latest Rate API. Besides, this tutorial will explain how to create a basic Ionic Angular currency converter app using the Exchangerate API through the HTTP client module API.
In this part 2, we will customizing the apps interface and add search filter for the currency selection and the results too.
HOW TO BUILD THE CURRENCY CONVERTER IN IONIC – PART 2
- Step 1 : Create search filter
- Step 2 : Add currency flags
- Step 3 : Customizing the apps interface
CREATE SEARCH FILTER
As we already have the currency selection and the conversion result, it will easier if we make the selection and the result have filtering function. To establish a search filter, we are utilizing a pipe filter, which is essentially a built-in functionality of ng2-search-filter. We will utilize the ng2-search-filter plugin on this tutorial.
We must now install ng2-search-filter, which is the main plugin.
Put the following command into action:
npm i ng2-search-filter --save
You can find its documentation here.
As every page in Ionic Angular having its own module so we can just add dependencies in its own module.
For example, we have a Home page, now in the home.module.ts file import the Ng2SearchPipeModule then add in the imports array as shown below:
//home.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { IonicModule } from '@ionic/angular';
import { FormsModule } from '@angular/forms';
import { HomePage } from './home.page';
import { HomePageRoutingModule } from './home-routing.module';
import { Ng2SearchPipeModule } from 'ng2-search-filter';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
Ng2SearchPipeModule,
HomePageRoutingModule
],
declarations: [HomePage]
})
export class HomePageModule {}
In the component class, add a property that work to keep the value changed when using a search bar.
//home.page.ts
import { Component, OnInit } from '@angular/core';
import { DataService } from "../services/data.service";
import { LoadingController } from '@ionic/angular';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
symbols: any;
codeCur: any = '';
descCur: any;
seleCur: any;
convData: any = [];
ratesData: any = [];
curAmount: any = '1.00';
crcTerm: any;
filterCur: any;
constructor(
private dataServer: DataService,
public loader: LoadingController ){}
ngOnInit() {
this.getSymbols();
}
// INITIAL
async getSymbols() {
await this.dataServer.getSymbols().then((data: any) => {
this.symbols = [];
for (var key in data.symbols) {
if (data.symbols.hasOwnProperty(key)) {
this.symbols.push({ "code": data.symbols[key].code, "desc": data.symbols[key].description });
}
}
});
}
async convertCurrency(base, amount) {
await this.dataServer.convCur(base, amount).then((data: any) => {
this.ratesData = Object.keys(data.rates)
.map(key => ({ name: key, value: data.rates[key] }))
});
this.convData = [];
for (let i = 0; i < this.symbols.length; i++) {
this.convData.push({
...this.symbols[i],
...(this.ratesData.find((itmInner) => itmInner.name === this.symbols[i].code))
}
);
}
}
async getRates() {
const loading = await this.loader.create({
message: 'Changing the currency',
duration: 2000
});
await loading.present();
await this.convertCurrency(this.codeCur, this.curAmount);
}
selectedCur(ev) {
let selCur = ev.detail.value;
let a = selCur.split("|");
this.codeCur = a[0];
this.descCur = a[1];
this.seleCur = a[0] + ' - ' + a[1];
}
}
Next, update the home.page.html to have search input and implement the filter function as a pipe in the ngFor using the ngModel property from the search bar.
//home.page.html
<ion-content [fullscreen]="true">
<ion-header>
<ion-toolbar>
<ion-title>FOREIGN EXCHANGE RATES</ion-title>
</ion-toolbar>
</ion-header>
<div id="slcContainer">
<ion-row>
<ion-col size="12" size-md>
<div class="titleSelect">Enter amount</div>
<ion-item>
<ion-input [(ngModel)]="curAmount" type="number" inputmode="decimal"></ion-input>
</ion-item>
</ion-col>
<ion-col size="12" size-md>
<div class="titleSelect">Select Currency</div>
<div style="display: flex;">
<ion-searchbar showClearButton="never" (ionFocus)="isOpen=true" id="searchCurr" placeholder=" Select a currency" value="{{seleCur}}"></ion-searchbar>
</div>
</ion-col>
</ion-row>
<ion-button expand="block" (click)="getRates()">Convert</ion-button>
<ion-modal [isOpen]="isOpen" (didDismiss)="isOpen=false">
<ng-template>
<ion-header>
<ion-toolbar>
<ion-title>Select a currency</ion-title>
<ion-buttons slot="end">
<ion-button (click)="isOpen=false">Close</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-searchbar placeholder=" Filter currency" [(ngModel)]="filterCur"></ion-searchbar>
<ion-list>
<ion-radio-group (ionChange)="selectedCur($event)" value="USD">
<ion-list-header>
<ion-label>Name</ion-label>
</ion-list-header>
<ion-item *ngFor="let i of symbols | filter : filterCur">
<ion-label>{{i.code}} - {{i.desc}}</ion-label>
<ion-radio slot="start" value="{{i.code}}|{{i.desc}}"></ion-radio>
</ion-item>
</ion-radio-group>
</ion-list>
</ion-content>
</ng-template>
</ion-modal>
<div *ngIf="convData.length > 0">
<ion-searchbar placeholder="Filter Currency" [(ngModel)]="crcTerm"></ion-searchbar>
</div>
<div>
<ion-card *ngFor="let d of convData | filter : crcTerm">
<div class="listRates">
<div class="ratesDetails">
<ion-card-subtitle>
{{d.name}} - {{d.desc}}
</ion-card-subtitle>
<ion-card-subtitle style="color:green;">
{{d.value}}
</ion-card-subtitle>
</div>
</div>
</ion-card>
</div>
</div>
</ion-content>
ADD CURRENCY FLAGS
For better experience, why not we give the results and the selection an image that represent their value. Here, we already prepared the image asset base on the currency code and put in the src/app/asset/flags.
Then, update the home.page.html to display the currency image.
//home.page.html
<ion-content [fullscreen]="true">
<ion-header>
<ion-toolbar>
<ion-title>FOREIGN EXCHANGE RATES</ion-title>
</ion-toolbar>
</ion-header>
<div id="slcContainer">
<ion-row>
<ion-col size="12" size-md>
<div class="titleSelect">Enter amount</div>
<ion-item>
<ion-input [(ngModel)]="curAmount" type="number" inputmode="decimal"></ion-input>
</ion-item>
</ion-col>
<ion-col size="12" size-md>
<div class="titleSelect">Select Currency</div>
<div style="display: flex;">
<ion-searchbar showClearButton="never" (ionFocus)="isOpen=true" id="searchCurr" placeholder=" Select a currency" value="{{seleCur}}">
<img onerror="this.src='../../assets/flags/wallet.png'" style="height:20px;margin-right: 10px;" src="../../assets/flags/{{codeCur | lowercase}}.png" alt="flags">
</ion-searchbar>
</div>
</ion-col>
</ion-row>
<ion-button expand="block" (click)="getRates()">Convert</ion-button>
<ion-modal [isOpen]="isOpen" (didDismiss)="isOpen=false">
<ng-template>
<ion-header>
<ion-toolbar>
<ion-title>Select a currency</ion-title>
<ion-buttons slot="end">
<ion-button (click)="isOpen=false">Close</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-searchbar placeholder=" Filter currency" [(ngModel)]="filterCur"></ion-searchbar>
<ion-list>
<ion-radio-group (ionChange)="selectedCur($event)" value="USD">
<ion-list-header>
<ion-label>Name</ion-label>
</ion-list-header>
<ion-item *ngFor="let i of symbols | filter : filterCur">
<ion-label>{{i.code}} - {{i.desc}}</ion-label>
<ion-radio slot="start" value="{{i.code}}|{{i.desc}}"></ion-radio>
</ion-item>
</ion-radio-group>
</ion-list>
</ion-content>
</ng-template>
</ion-modal>
<div *ngIf="convData.length > 0">
<ion-searchbar placeholder="Filter Currency" [(ngModel)]="crcTerm"></ion-searchbar>
</div>
<div>
<ion-card *ngFor="let d of convData | filter : crcTerm">
<div class="listRates">
<div class="ratesFlag">
<img style="margin-right: 10px;" src="../../assets/flags/{{d.name | lowercase}}.png" alt="flags" onerror="this.src='../../assets/flags/wallet.png'">
</div>
<div class="ratesDetails">
<ion-card-subtitle>
{{d.name}} - {{d.desc}}
</ion-card-subtitle>
<ion-card-subtitle style="color:green;">
{{d.value}}
</ion-card-subtitle>
</div>
</div>
</ion-card>
</div>
</div>
</ion-content>
CUSTOMIZING THE APPS INTERFACE
Finally, we will update the apps interface. Add the following style code in the home.page.scss:
//home.page.scss
#slcContainer {
width: 80vw;
margin: 0 auto;
margin-top: 16px;
}
.titleSelect {
margin: 10px 0px;
}
.listRates {
display: flex;
padding: 10px;
width: 100%;
.ratesFlag {
img {
height: 20px;
}
}
}
#searchCurr {
padding-top: 0px;
Add this style in src/global.scss to change the currency selector search bar. This code will remove the search icon from the search bar.
//global.scss
/*
* App Global CSS
* ----------------------------------------------------------------------------
* Put style rules here that you want to apply globally. These styles are for
* the entire app and not just one component. Additionally, this file can be
* used as an entry point to import other CSS/Sass files to be included in the
* output CSS.
* For more information on global stylesheets, visit the documentation:
* https://ionicframework.com/docs/layout/global-stylesheets
*/
/* Core CSS required for Ionic components to work properly */
@import "~@ionic/angular/css/core.css";
/* Basic CSS for apps built with Ionic */
@import "~@ionic/angular/css/normalize.css";
@import "~@ionic/angular/css/structure.css";
@import "~@ionic/angular/css/typography.css";
@import '~@ionic/angular/css/display.css';
/* Optional CSS utils that can be commented out */
@import "~@ionic/angular/css/padding.css";
@import "~@ionic/angular/css/float-elements.css";
@import "~@ionic/angular/css/text-alignment.css";
@import "~@ionic/angular/css/text-transformation.css";
@import "~@ionic/angular/css/flex-utils.css";
/*
* App Global CSS
* ----------------------------------------------------------------------------
* Put style rules here that you want to apply globally. These styles are for
* the entire app and not just one component. Additionally, this file can be
* used as an entry point to import other CSS/Sass files to be included in the
* output CSS.
* For more information on global stylesheets, visit the documentation:
* https://ionicframework.com/docs/layout/global-stylesheets
*/
/* Core CSS required for Ionic components to work properly */
@import "~@ionic/angular/css/core.css";
/* Basic CSS for apps built with Ionic */
@import "~@ionic/angular/css/normalize.css";
@import "~@ionic/angular/css/structure.css";
@import "~@ionic/angular/css/typography.css";
@import '~@ionic/angular/css/display.css';
/* Optional CSS utils that can be commented out */
@import "~@ionic/angular/css/padding.css";
@import "~@ionic/angular/css/float-elements.css";
@import "~@ionic/angular/css/text-alignment.css";
@import "~@ionic/angular/css/text-transformation.css";
@import "~@ionic/angular/css/flex-utils.css";
/* Custom CSS for Currency Selector Search Bar */
#searchCurr>div>ion-icon {
display: none!important;
}
#searchCurr>div>input {
padding-left: unset;
padding-right: unset;
-webkit-padding-start: 15px;
padding-inline-start: 15px;
-webkit-padding-end: 15px;
padding-inline-end: 15px;
}
If everything is good, we already have a functioning app that make conversion and have a better interface like video below.
See this project on GitHub.