When it comes to saving data in an Ionic 2 mobile application, there are many ways to get the job done. You can use the classic HTML5 local storage, but run the risk of compatibility problems between all available devices. You can use SQLite, which is part of Ionic Native, but that will only work for Android and iOS and has more of a mobile API. You can also use SqlStorage, but that is a very proprietary solution. This brings us to localForage from Mozilla.
Mozilla advertises localForage as a wrapper to IndexedDB, WebSQL and localStorage which will offer maximum compatibility across the grid.
We’re going to see how to include localForage in our application which is a valid option for Ionic 2.
I actually first heard of localForage from Nolan Lawson who was a guest on my podcast, PouchDB and its Usefulness in Development. He described it as a better solution to PouchDB if you have no plans to offer synchronization support in your application.
To keep this easy to understand we’re going to create a new Ionic 2 project and include localForage in it. Using a Command Prompt (Windows) or Terminal (Mac and Linux), execute the following:
ionic start ForageProject blank --v2
cd ForageProject
ionic platform add ios
ionic platform add android
There are a few things to note in the above commands. The --v2
tag means we are creating an Ionic 2 project with TypeScript. This means you need to have the Ionic 2 CLI. Also note that I am adding the iOS platform. If you’re not using a Mac, you cannot build for the iOS platform.
The next thing we need to do is install localForage and the TypeScript type definitions that go with it. Using the Terminal or Command Prompt, execute the following:
npm install localforage --save
Above will install the JavaScript library. JavaScript libraries don’t play nice in a TypeScript application. To install the type definitions we’ll need a package called Typings. Execute the following to install Typings and the necessary type definitions:
npm install -g typings
typings install dt~localforage --save --global
Now we can focus on the code.
This is going to be a very simple project. We’ll be able to load the data from localForage and add data to localForage. This data will be presented on the screen as a list.
We’re going to start with the TypeScript logic before we touch the UI. Open the project’s app/pages/home/home.ts file and include the following code:
import {Component} from '@angular/core';
import {NavController, AlertController} from 'ionic-angular';
declare var require: any;
const localforage: LocalForage = require("localforage");
@Component({
templateUrl: 'build/pages/home/home.html'
})
export class HomePage {
private people: Array<Object>;
public constructor(private navController: NavController, private alertController: AlertController) {
localforage.getItem("people").then((result) => {
this.people = result ? <Array<Object>> result : [];
}, (error) => {
console.log("ERROR: ", error);
});
}
public save() {
let prompt = this.alertController.create({
title: "New Person",
message: "Enter the first and last name of a person you want to add.",
inputs: [
{
name: "firstname",
placeholder: "First Name"
},
{
name: "lastname",
placeholder: "Last Name"
},
],
buttons: [
{
text: "Cancel",
handler: data => { }
},
{
text: "Save",
handler: data => {
if(data.firstname != "" && data.lastname != "") {
this.people.push({
firstname: data.firstname,
lastname: data.lastname
});
localforage.setItem("people", this.people);
}
}
}
]
});
prompt.present();
}
}
There is a lot going on in the above code. We should break it down to make it easier to understand.
We start things off by importing some very basic Ionic 2 components. However, we are also importing localForage like so:
declare var require: any;
const localforage: LocalForage = require("localforage");
This import is how it is said to be done in the official localForage documentation.
Inside the HomePage
class we have a public array people
which will be bound to the UI. It will hold all of the saved data. In the constructor
method we do a bit of initialization:
public constructor(private navController: NavController, private alertController: AlertController) {
localforage.getItem("people").then((result) => {
this.people = result ? <Array<Object>> result : [];
}, (error) => {
console.log("ERROR: ", error);
});
}
Using localForage is asynchronous and you can use callbacks or promises. I’ve chosen to use a promise. If the result of the promise is null, it means the key did not exist, which explains the ternary operation.
Now there is a lot happening in the save
method, but it is really just the bootstrap code for an Ionic 2 alert. What we care about is the following:
if(data.firstname != "" && data.lastname != "") {
this.people.push({
firstname: data.firstname,
lastname: data.lastname
});
localforage.setItem("people", this.people);
}
We make sure the first name and last name were entered. If they were, add them to the public array and then save that public array in localForage.
The beauty of localForage is that you can store any data type without having to worry about parsing it out. This is a benefit in addition to the compatibility that it offers.
Now we can take a look at the HTML UI for this application. Open the project’s app/pages/home/home.html file and include the following markup:
<ion-header>
<ion-navbar>
<ion-title>
Ionic Local Forage
</ion-title>
<ion-buttons end>
<button (click)="save()">
<ion-icon name="add"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-list>
<ion-item *ngFor="let person of people">
{{person.firstname}} {{person.lastname}}
</ion-item>
</ion-list>
</ion-content>
We essentially have a header with a button in it and a list that shows our public array. The UI in this application is very basic.
There are many options for saving data when it comes to Ionic 2 mobile applications. The localForage offering by Mozilla is a very easy to use key-value option that has very good compatibility. You can store any data type without having to worry about parsing or serializing the data like you would with HTML5 local storage or similar.