Consistent with my reknewed love for the web, I’ve been having fun developing a little Google Tasks mobile app. My plan is to target Windows Phone since there aren’t a lot of good tasks apps on that platform - and because that’s the platform I run!

At the moment I’m really loving Ionic. It’s a framework for building Angular apps for mobile (build on Cordova), but gives you a ton of the nice mobile animations, hamburger menu templates, and lovely Angular-friendly wrappers for other mobile goodness.

Check out the progress:

Ionic powers my Google Tasks app

Moving things offline with IndexedDb

One of the problems with the current batch of Google Tasks apps for Windows phone is that they don’t work well offline.

So I was on the hunt for storage solutions that would play nice in a browser env. LocalStorage was nice and simple (basically a key-value string pair), but I needed something with a little more power that I could query JS objects without a bunch of marshalling and drama.

Enter IndexedDb.

If you haven’t played with it before, IndexedDb is a super powerful client side storage API for the browser. You can store complex objects, index and query fields, access it from Web Workers, and even do transactions!

But the API. Oh, the API.

It’s low level.

Very. Low. Level.

It’s so low level, that the Mozilla Docs even warn you to use a wrapper to make things nice.


flickr photo shared by demandaj under a Creative Commons ( BY-NC-ND ) license

Enter the Dexie.js

So the champs at Dexie.js have come to the rescue with a super simple, Promise (or callback) based API that will have you storing, querying and otherwise CRUDing from your browser in no time.

Sparking up your fresh Db is a matter of supplying your Database name, and the “table” fields you want to index (in my case tasks and taskLists since that marries nicely with the Google Tasks API I’ll be interacting with):

var db = new Dexie(YOUR_DB_NAME);
db.version(1).stores({
    tasks: "id,name,lastUpdated,taskListId,status", 
    taskLists: "id,name,lastUpdated"
});
db.open(); // After this line, database is ready to use.

With your database in place, your first query is just a nice chainable call away:

this.getTasksForList = function(taskListId) {
    var tasks = db.tasks.where('taskListId').equals(taskListId).sortBy('position');
    return tasks;
};

And inserts are just as trivial:

this.pushTaskList = function(taskList) {
    return db.taskLists.put(taskList);
};

Super simple.

And everything is promise based, so using Dexie.js in an Angular app is a snack. I wrap up my little Dexie-based Tasks API in and IndexedDbService , and in my controller I can go a-promising…

IndexedDbService.getTasksForList($scope.tasklistId).then(function(tasks) {
    $scope.tasklist = tasks;
});

All kinds of wonderful.

And the docs are also really well done. So much to love here!

If you’re in the market for a more palletable approach to the awesomeness that is IndexedDb, definitely go check out Dexie.js.

Great work team!