Late last year I wrote the article PhoneGap and offline storage… which was an introduction to using the Web SQL API to store information for your application. The article centred around using the native browser API calls to be able to store your information. In the past few months I have done a lot more work with PhoneGap and offline storage and wanted to bring you up-to-date with the methodologies I use when it comes to storing data to your device.

Web SQL

One of the major differences from this article to the last is the lack of Web SQL. All my recent app development revolves around using the Local Storage API instead… For anybody wondering ‘why?’ the simple answer is, Web SQL is old and deprecated. I expect to see support for WebSQL disappearing in new versions of browsers in the not-so-distant future.

Local Storage

Local Storage is one of the simplest ways to store information for your web app, even using the native API calls. It works on a simple key/value storage system and therefore you can easily pull in masses of JSON information and store it with a key of e.g. ‘products’.

The native API calls look something like this:

localStorage.setItem("lastname", "Smith");

Simple, huh?

AngularJS

Most of the PhoneGap apps I have developed have been written using AngularJS which is my first choice for JS frameworks, it allows me to structure my apps cleanly and also has some cool modules such as routing and animation.

Now you may be wondering what Angular has to do with this article? Well it’s simple, it’s all about structure.

When I’m storing information to Local Storage I tend to use Lawnchair which allows you to create collections of objects and store them with ease.

Before I jump in to some code, I want to talk a bit more about processes.

There are multiple ways you can pull down the information and use it, for example:

  • Pull down the information required by the page on each page load and display it
  • Pull down the information required by the page and store it for future use
  • Synchronise the data in a routine that allows your page loads to only use local information

In my opinion, the most sensible way to handle this is in a synchronisation routine. When the app first runs AngularJS by default fires the run function:

Project.run(function($rootScope, $location, $route...

In this function we would run a check to see if remote information is fresher than the information stored on the device, and if so update it. The individual pages then can pull the information directly from Local Storage which in turn speeds up your app and makes sure it will always work – connection or no connection.

Code

Before we get our hands dirty, make sure you have downloaded copies of Angular JS, Lawnchair… and the Lawnchair DOM adaptor.

AngularJS isn’t 100% necessary for this tutorial, if you have a clear understanding of Javascript you will be able to follow what it is I’m doing.

First of all, create a basic AngularJS instance:

var Project = angular.module('Project');
    var storage_name = 'Project-storage';
    Project.run(function($rootScope, remoteResources){
    $rootScope.api_base = "http://your-domain.com/api/";
});

The storage_name variable is the name of the collection of Lawnchair objects.

Notice we also gave the run function access to a Factory called ‘remoteResources’, let’s create that now:

Project.factory('remoteResources', function($rootScope, $http){
    var resource = {};

    resource.checkForUpdates = function(){
    };

    resource.getInformation = function(){
    };

    return resource;
});

Awesome! We now need to create an instance of Lawnchair and assign it to $rootScope to make it accessible to other areas of your application. Back inside your run function:

$rootScope.store = Lawnchair({name: storage_name }, function(e){
    console.log('Storage open');
});

We can now access the object above throughout our app to get information from and put information in to it. Below that we need to call our checkForUpdates function to make sure we are always pulling down fresh information.

$rootScope.store = Lawnchair({name: storage_name }, function(e){
    console.log('Storage open');
});

remoteResources.checkForUpdates();

Inside the checkForUpdates function, we want to obtain the last updated date from the remote API and check if it’s newer than ours – this may look something like this:

resource.checkForUpdates = function(){
    // Check our last updated date on the device
    $rootScope.store.get('last_sync', function(last_sync){
        last_local_update = last_sync.value;

        $http({
            method: 'GET',
            url: $rootScope.api_base + '/updates/last?' + new Date().getTime()
        })
        .success(function(data){
            var last_remote_update = data.date;

            // Check if remote info is fresher than local
            if(last_remote_update > last_local_update || last_local_update === null){
                // Run resource functions
                resource.getInformation();
                // Update last update date locally
                $rootScope.store.save({
                    key: 'last_sync',
                    value: new Date()
                })
            }
        });
    });
};

Hopefully the above makes sense, but to put it simply we grab the local last updated date and then run a HTTP request to check the remote APIs last updated date – check if the remote info is fresher than the local, and if so run the getInformation function. We then update our local date to ensure we know when our information was updated.

In the last bit of the tutorial, I’ll show you how to obtain bits of remote information and store it using Lawnchair although if you have managed to follow this tutorial up to this point you will probably already be aware how to do this.

Now jump in to your getInformation function and lets create our HTTP request:

resource.getInformation = function(){
    // Run a GET request against the information API call
    $http({
        method: 'GET',
        url: $rootScope.apiBase + '/information?'+new Date().getTime()
    }).
    success(
        function(data){
            // Store the retrieved information with a set key
            $rootScope.store.save({
                key: 'information',
                value: data
            });
        }
    );
};

Once again, we call our API – pull down the information and store it using Lawnchair. To verify the data has been obtained you can check it using the developer tools in Chrome.

Go to Tools → Developer Tools -> Resources -> Local Storage (left panel) and you will see your items stored there.

To simplify, the 2 method calls you will mainly be using with Lawnchair are save and get:

$rootScope.store.get('key_of_item', function(item){
    console.log('Retrieved item:');
    console.log(item);
});
$rootScope.store.save({
    key: 'key_of_item',
    value: objects
});

Remember you can store a full set of JSON objects OR a string of text.

As usual, comments are appreciated and don’t hesitate to ask any questions :)