Ionic 5|4 Adding Ionic Offline Storage using SQLite Cordova Plugin

In this post, we’ll discuss how to use SQLite storage in an Ionic application using Cordova’s cordova-sqlite-storage plugin. In Ionic’s Angular, we use Native wrapper to access SQLite storage in a native device.

The SQLite type of storage is used by most of the Native devices like android. It is a relational database management system which is available in a device itself to store local data on a device. Storage capacity mainly depends on device memory thus provides a good space to do common tasks on a local device.

In a portable device, storage helps a developer to store local data like user settings, offline records, profile preferences etc. Hybrid Applications built using Ionic Framework can easily access and use Native storage systems like SQLite. Ionic Storage can be used in Web as well as in native devices but web uses LocalStorage and Native device use SQlite based storage system. The selection of storage type is managed by the Ionic framework itself.

Application developers sometimes need to save a bunch of information on the user side to control some features and provide some offline functionalities to application users, in that case, local storage proves very handy. Using Ionic’s Native storage plugin we can storage key-value pairs which may have any type of data from a simple string or integers to JSON objects. But this locally stored data will remain until the application is Uninstalled or device is formatted.

LocalStorage engines are managed by the plugin itself according to OS on which application is installed or running like in Native app context Storage will be done using SQLite, which is one of the most stable and most preferred file-based storage databases. On Progressive Web Apps platform IndevedDB, WebSQL or localStorage is chosen in a defined order.

 

Also, Check:

Ionic 4 | Storage Tutorial in Ionic using Native Storage Plugin

Complete SQLite CRUD Tutorial for Ionic 4 Angular Applications

 

Note: Ionic SQLite Database and Ionic Storage using SQLite plugin work diffently. SQLite Database acts like a real database where SQL queries can be executed to do CRUD operations. But Ionic Storage is a substituting to LocalStorage to save data in Key-Value pairs which we discussed here.

 

in Ionic Tutorial check this post.

Let’s start the implementation of SQLite Plugin in Ionic Application

# Update Ionic CLI

We are going to create Ionic Angular application in latest version 6.6.0. Run the following command to install or update the @ionic/cli package to build Ionic 5 application using Angular version 8

$ npm install -g @ionic/cli

 

# Create a new Ionic application

Now we'll create a new Ionic application using Angular framework by adding --type=angular option with a blank template

$ ionic start ionic-sqlite-tutorial blank --type=angular

move to the application directory

$ cd ionic-sqlite-tutorial

 

# Install Cordova and Ionic Native Plugin

To enable SQLite storage in the Ionic application, we'll install Cordova plugin and Native wrapper module by running below commands

$ ionic cordova plugin add cordova-sqlite-storage
$ npm install --save @ionic/storage

 

# Import declare plugin in Application's module file

In the app.module.ts file, import plugin then adds in Imports array in NgModule. Replace below code:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';

import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';

import { IonicStorageModule } from '@ionic/storage';

@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [
    BrowserModule, 
    IonicModule.forRoot(), 
    AppRoutingModule,
    IonicStorageModule.forRoot()
  ],
  providers: [
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

 

After adding the plugin to the app's main module, we can now use Native Storage anywhere in the application. Here we will use it in the home component.

In the home.page.ts file, import plugin then creates an instance in component's constructor.

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

import { Storage } from '@ionic/storage';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage {

  constructor(private storage: Storage) {
    // set a key/value
    this.storage.set('name', 'Max');

    // Or to get a key/value pair
    this.storage.get('age').then((val) => {
      console.log('Your age is', val);
    });
  }
}

In the above code, we just simply setting and getting the string value.

 

Set a Value in a Key

set() : Set the value for the given key. Returns a Promise that resolves when the key and value are set

  // set a key/value
  setValue(key: string, value: any) {
    this.storage.set(key, value).then((response) => {
      console.log('set' + key + ' ', response);

      //get Value Saved in key
      this.getValue(key);

    }).catch((error) => {
      console.log('set error for ' + key + ' ', error);
    });
  }

 

Get Value in a Key

get() : Get the value associated with the given key. Returns a promise with the value of the given key

  // get a key/value pair
  getValue(key: string) {
    this.storage.get(key).then((val) => {
      console.log('get ' + key + ' ', val);
      this.data[key] = "";
      this.data[key] = val;
    }).catch((error) => {
      console.log('get error for ' + key + '', error);
    });
  }

 

Remove a key/value pair

remove() : Remove any value associated with this key. Returns a promise that resolves when the value is removed

  // Remove a key/value pair
  removeKey(key: string) {
    this.storage.remove(key).then(() => {
      console.log('removed ' + key);
      this.data[key] = "";
    }).catch((error) => {
      console.log('removed error for ' + key + '', error);
    });
  }

 

Current Storage Engine Used

Get the name of the driver being used.

  //Get Current Storage Engine Used
  driverUsed() {
    console.log("Driver Used: " + this.storage.driver);
  }

Traverse key/value pairs

forEach() : Iterate through each key,value pair. Returns a promise that resolves when the iteration has finished.

  traverseKeys() {
    this.storage.forEach((value: any, key: string, iterationNumber: Number) => {
      console.log("key " + key);
      console.log("iterationNumber " + iterationNumber);
      console.log("value " + value);
    });
  }

 

All Stored Keys

keys() : Returns a promise that resolves with the keys in the store.

  // Traverse key/value pairs
  listKeys() {
    this.storage.keys().then((k) => {
      console.table(k)
    });
  }

 

Total Keys Stored

length() : Returns a promise that resolves with the number of keys stored.

  // Total Keys Stored
  getKeyLength() {
    this.storage.length().then((keysLength: Number) => {
      console.log("Total Keys " + keysLength);
    });
  }

You can check more options here

Finally out component will look like this

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

import { Storage } from '@ionic/storage';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage {

  data: any;

  constructor(
    private storage: Storage
  ) {
    this.data = {};
    //Set String Value
    this.setValue("name", "Freaky Jolly");
    //Set Integer Value
    this.setValue("phone", 8908904);

    let sampleObj = [
      {
        country: "United States of America",
        address: "638 Fahey Overpass",
        phone: "257.255.3201"
      }, {
        country: "United States of America",
        address: "141 Schowalter Mount",
        phone: "1-868-497-5043 x73289"
      }, {
        country: "United States of America",
        address: "025 Schultz Via",
        phone: "1-814-823-5520 x68656"
      }
    ];

    //Set Object Value
    this.setValue("offices", sampleObj);
  }


  // set a key/value
  setValue(key: string, value: any) {
    this.storage.set(key, value).then((response) => {
      console.log('set' + key + ' ', response);

      //get Value Saved in key
      this.getValue(key);

    }).catch((error) => {
      console.log('set error for ' + key + ' ', error);
    });
  }

  // get a key/value pair
  getValue(key: string) {
    this.storage.get(key).then((val) => {
      console.log('get ' + key + ' ', val);
      this.data[key] = "";
      this.data[key] = val;
    }).catch((error) => {
      console.log('get error for ' + key + '', error);
    });
  }

  // Remove a key/value pair
  removeKey(key: string) {
    this.storage.remove(key).then(() => {
      console.log('removed ' + key);
      this.data[key] = "";
    }).catch((error) => {
      console.log('removed error for ' + key + '', error);
    });
  }

  //Get Current Storage Engine Used
  driverUsed() {
    console.log("Driver Used: " + this.storage.driver);
  }

  // Traverse key/value pairs
  traverseKeys() {
    this.storage.forEach((value: any, key: string, iterationNumber: Number) => {
      console.log("key " + key);
      console.log("iterationNumber " + iterationNumber);
      console.log("value " + value);
    });
  }

  // Traverse key/value pairs
  listKeys() {
    this.storage.keys().then((k) => {
      console.table(k)
    });
  }

  // Total Keys Stored
  getKeyLength() {
    this.storage.length().then((keysLength: Number) => {
      console.log("Total Keys " + keysLength);
    });
  }


}

To call these methods, add below HTML in home.page.html

<ion-header>
  <ion-toolbar>
    <ion-title>
      Ionic 4 Native Storage
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content padding>
  Saved Keys!


  <ion-grid>
    <ion-row>
      <ion-col size="3">
        <strong>String</strong>
      </ion-col>
      <ion-col>:
        {{data.name}}<ion-icon name="trash" (click)="removeKey('name')"></ion-icon>
      </ion-col>
    </ion-row>
    <ion-row>
      <ion-col size="3">
        <strong>Integer</strong>
      </ion-col>
      <ion-col>:
        {{data.phone}}<ion-icon name="trash" (click)="removeKey('phone')"></ion-icon>
      </ion-col>
    </ion-row>
    <ion-row>
      <ion-col>
        <strong>JSON Object</strong><ion-icon name="trash" (click)="removeKey('offices')"></ion-icon>
            <ion-card *ngFor="let item of data.offices; let i = index">
                <ion-card-header>
                    <ion-card-title>Office {{i+1}}
                    </ion-card-title>
                </ion-card-header>
              <ion-card-content>
                <p><strong>Country</strong>: {{item.country}}</p>
                <p><strong>Address</strong>: {{item.address}}</p>
                <p><strong>Phone</strong>: {{item.phone}}</p>
              </ion-card-content>
            </ion-card>
      </ion-col>
    </ion-row>
  </ion-grid>


  <ion-button size="small" (click)="driverUsed()">Get Storage Driver Used</ion-button>
  <ion-button size="small" (click)="traverseKeys()">Loop through All Stored Keys</ion-button>
  <ion-button size="small" (click)="listKeys()">Get Stored Keys</ion-button>
  <ion-button size="small" (click)="getKeyLength()">Get Length Stored Keys</ion-button>


</ion-content>

Here we discussed How we can Integrate Cordova' Storage Native plugin in Ionic Application to Store Values in different formats and retrieve them as per application requirements.

1 thought on “Ionic 5|4 Adding Ionic Offline Storage using SQLite Cordova Plugin

Leave a Reply

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