Adding database synchronization to your PhoneGap project

This post is more than 2 years old.

For the past few days I've been working on a proof of concept PhoneGap application that demonstrates an example of database synchronization. This is a fairly complex topic and I'm only going to demonstrate one version of this, but I hope the concepts, code, and example application are useful to people hoping to tackle the same problem.

Before we start digging into code, let me explain what the application will demonstrate and the type of synchronization it will use. Our sample application is going to use a built-in database for documentation. Most mobile applications don't really have a lot of documentation. Anything that complex may not make sense on mobile anyway. But for whatever reason you want to use, the application has a large set of documents stored in the database.

This documentation may or may not ship with the application, but we want the application to sync with a remote server in order to get the latest and greatest documentation. Our synchronization "rules" will be simple:

  • If the remote server adds new docs, the app needs to get it.
  • If the remote server updates existing docs, the app needs to update its copy.
  • If the remote server deletes a doc, the app needs to delete its local copy.

In this scenario, we don't have to worry about user generated content and handling updates bidirectionally. That allows us to simplify things quite a bit.

We have two pieces to this proof of concept, the server and the client. I'm going to quickly talk about the server-side code, but as this is mainly a post about PhoneGap, I won't go into deep detail. I built a very simple ColdFusion application using ORM to allow me to add, edit, and delete objects I called "helpdocuments". These documents contained:

  • A title (short string)
  • A body (not so short string)
  • A field representing when the document was last updated
  • A token (built around a UUID, more on why we need this later)
  • A deleted flag (to support 'soft deletes')

You can find the code for this simple application attached to this blog entry. But really - it's just simple CRUD and web forms:

Outside of the service component I'll be using to expose this data remotely, you really don't have to worry about the details and forms here. Let's turn our attention to the client side now.

First off - do not forget that PhoneGap provides a wrapper to WebSQL, an embedded database you can use with JavaScript. You can check out the API docs as well as the video demonstration over on Adobe TV. My application will create a mirror version of the remote database to store a copy of the documentation. This involves:

  • Creating the initial database
  • Creating the empty table
  • Asking the server for data, and later on, asking the server for new data
  • Rendering the data (in our case, I'm just going to list the titles of the help docs)

Since the actual display is rather trivial, I'll show the HTML for the application first:


<!DOCTYPE html>
<html>
<head>
	<title>PhoneGap SyncDB Test</title>
	<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
	<script type="text/javascript" src="cordova-1.5.0.js"></script>
	<script type="text/javascript" src="main.js"></script>
</head>
<body onload="init()">

<div id="docs"></div>

</body>
</html>

Yeah, that's it. Obviously a real application would have a bit more meat to it. Let's take a look at main.js, the core logic file for the application. This one is a bit more complex so we're going to take it in chunks.


var db;
//var updateurl = "http://localhost/testingzone/dbsyncexample/serverbackend/service.cfc?method=getupdates&returnformat=json";
var updateurl = "http://www.raymondcamden.com/demos/2012/apr/3/serverbackend/service.cfc?method=getupdates&returnformat=json";

function init() {
	document.addEventListener("deviceready",startup);
}

In the first block, we've got a few variable definitions. The db variable will contain a reference to my database. The updateurl is simply the remote server. (And by the way, that URL isn't going to work after I publish this article.) Our init function listens for PhoneGap's deviceready event. This is PhoneGap's way of saying, "It's Business Time."


function startup() {
	console.log("Starting up...");
	db = window.openDatabase("main","1","Main DB",1000000);
	db.transaction(initDB,dbError,dbReady);
}

Here we have the startup function. It opens the database and begins a transaction. Note that I could have put the logic inside an anonymous function within the transaction call. You're going to see an example of that later. But in my opinion, the initialization routine would be complex enough to warrant moving it into its own function to keep things better organized. (It really isn't that complex, but I still feel like it was the right decision to make.)

Here's the error handler. Again - this would typically be more robust in a production environment:


function dbError(e) {
	console.log("SQL ERROR");
	console.dir(e);
}

Now let's look at initDB:


function initDB(tx) {
	tx.executeSql("create table if not exists docs(id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, body TEXT, lastupdated DATE, token TEXT)");
}

You can see my table creation scheme uses columns that match up with my server. The only column missing is the "soft delete" one. My thinking here was that while my server wants to keep deleted documents around so that they can (possibly) be restored later, my mobile application should try to stay as thin as possible.

This is a great time now to talk about the token column. Both my server and client side have it. Why? In order to keep documents in sync from one database server to my mobile applications, I need a way to uniquely identify records. I'm not even sure if the WebSQL client (SQLite) supports inserts with assigned primary keys, but in my mind, the easiest way to handle this was to simply let each "side" handle the primary keys their own way and use the UUID as a way to connect them. This could possibly be done better.

After our table creation script runs, we finally get to dbReady:


function dbReady() {
	console.log("DB initialization done.");
	//begin sync process
	if(navigator.network && navigator.network.connection.type != Connection.NONE) syncDB();
	else displayDocs();
}

As the comment says, this is where we begin our sync process. However, we only do this if the client is actually online. If it isn't, we immediately display our docs. On first run we won't have any, but after that we'll have something. This ensures that offline or online, we're going to support the user reading and interacting with the database.

Ok - now for the complex portion. Let's look at our synchronization function.


function syncDB() {
	$("#docs").html("Refreshing documentation...");

I begin with a simple message letting the user know that important things are going on. Really important things.


	var date = localStorage["lastdate"]?localStorage["lastdate"]:'';
	console.log("Will get items after "+date);

Local storage? I thought we were using a database? We are! But there's no reason we can't use both. While working on this proof of concept I had an interesting problem. I want to minimize the amount of data going back and forth between the application and the server. To do that, my application needs to tell the server what its most recent update was. One way of doing that would be run SQL against itself and get the date on the last updated document. That works fine... except for deletes. If the most recent update on the server was to delete something, then the client's most recent date wouldn't match. As I said above, we aren't keeping those deleted records. So as a compromise, I simply used a value in localStorage. Later on you will see where this gets updated.


	$.get(updateurl, {date:date}, function(resp,code) {
		console.log("back from getting updates with "+resp.length + " items to process.");

Here's our server call. It basically pings the remote code and passes in a date. The server asks for all records modified since that date. The result is an array of objects.


resp.forEach(function(ob) {
	db.transaction(function(ctx) {
		ctx.executeSql("select id from docs where token = ?", [ob.token], function(tx,checkres) {
			if(checkres.rows.length) {
				console.log("possible update/delete");
				if(!ob.deleted) {
					console.log("updating "+ob.title+ " "+ob.lastupdated);
					tx.executeSql("update docs set title=?,body=?,lastupdated=? where token=?", [ob.title,ob.body,ob.lastupdated,ob.token]);
				} else {
					console.log("deleting "+ob.title+ " "+ob.lastupdated);
					tx.executeSql("delete from docs where token = ?", [ob.token]);
				}
			} else {
				//only insert if not deleted
				console.log("possible insert");
				if(!ob.deleted) {
					console.log("inserting "+ob.title+ " "+ob.lastupdated);
					tx.executeSql("insert into docs(title,body,lastupdated,token) values(?,?,?,?)", [ob.title,ob.body,ob.lastupdated,ob.token]);
				}
			}

		});
	});
});

Holy smokes that's a lot! Let's take it piece by piece. We begin with a simple forEach iterator over the array. For each item, we need to see if already exists. That's done in the SQL that checks for the token.

If a record exists, then we either need to update it, or delete it. Remember that our server keeps deleted documents and simply flags them. You can see my check for that flag here:


if(!ob.deleted)

If the object wasn't deleted, we perform an update. If it was deleted, we perform a delete.

On the other side of the conditional, we only need to do an insert if the object isn't a delete.

Finally - we update our localStorage flag and call displayDocs too. Here's the display function - and again - this was built to be simple.


function displayDocs() {
    db.transaction(function(tx) {
        tx.executeSql("select title from docs order by title asc", [], function(tx, results) {
            var s = "<h2>Docs</h2>";
            for(var i=0; i<results.rows.length; i++) {
                s += results.rows.item(i).title + "<br/>";
            }
            $("#docs").html(s);
        });
    });
}

The end result is an application that updates its data when online and continues to work fine offline. You can download the entire code base below. Any questions?

Download attached file.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Raymond Camden posted on 4/4/2012 at 1:04 AM

Sorry for the lack of tabbing above folks. Not sure why. I used Sublime Text 2 for all of my work and I'm assuming something pasted wrong.

Comment 2 by Mikel posted on 4/4/2012 at 3:25 PM

Oh! Very nice! Thanks for this example!

Comment 3 by Phillip Senn posted on 4/4/2012 at 6:56 PM

There's a lot to digest here, and I thank you as always for taking the time to blog. One thing I noticed is that during development, it might be nice to drop the table in initDB before creating it. Just in case you change the schema. It's not as trivial as one would think because (I think) you have to wait for the callback before creating it again.

Comment 4 by Raymond Camden posted on 4/4/2012 at 6:57 PM

@Phillip: Dude... get this. I removed this line from my blog post:

//tx.executeSql("drop table docs");

That's _exactly_ what I was doing during testing.

Comment 5 by Phillip Senn posted on 4/4/2012 at 7:01 PM

I use the following to test for whether their online or not:

if (navigator.onLine) {
$('#myOnline').text('Your Internet status is: online.');
setTimeout(Sync,3000); // Don't sync until they've paused for a few seconds.
} else {
$('#myOnline').text('Your Internet status is: offline.');
}

window.addEventListener("offline", function(e) {
$('#myOnline').text('Your new Internet status is: offline.');
}, false);

window.addEventListener("online", function(e) {
$('#myOnline').text('Your new Internet status is: online.');
Sync(); // This will start the sync the moment they walk back into Wi-Fi.
}, false);

Comment 6 by Raymond Camden posted on 4/4/2012 at 7:04 PM

I tried navigator.onLine, but on my device, it reported me as online while in Airplane Mode.

Comment 7 by Phillip Senn posted on 4/4/2012 at 9:35 PM
Comment 8 by Terry Collinson posted on 4/15/2012 at 7:29 PM

Thanks very much Ray. Amazed not more questions on this great post. On first run the table creates fine but I don't have the last update date in my local storage. I know there hasn't been an update yet so do I have to create it manually to start things off? I am using Chrome on the desktop and can see other local storage with the JavaScript tool. I have replaced the server link providing the JSON

Comment 9 by Raymond Camden posted on 4/16/2012 at 12:23 AM

Hmm. So the client-side code should be making the request and passing an empty date string, which should make the server return everything. Can you add some debugging (simple writeLogs) to the CFC to see if it is doing that?

Comment 10 by Raymond Camden posted on 4/16/2012 at 12:24 AM

Oh - and this may not be obvious - but did you _write_ some docs using the server-side code first?

Comment 11 by Terry Collinson posted on 4/18/2012 at 4:07 PM

All I have done is to change the url of the cfc to http://wildlifehero.com/api.... I used your API example of a while back to create the JSON from an existing table. So I assume the date format is not an issue. I don't see any call to the cfc in the Chrome Network tab - not sure if I should. If you can confirm the JSON is ok I will add some looking as you suggested. Thanks

Comment 12 by Raymond Camden posted on 4/18/2012 at 5:34 PM

When I run your URL I get a file not found error.

Comment 13 by Terry Collinson posted on 4/18/2012 at 7:14 PM

sorry I missed out the www in the post. It is in my code http://www.wildlifehero.com... Thanks

Comment 14 by Raymond Camden posted on 4/18/2012 at 7:57 PM

Terry, that looks right to me. At this point, I'd continue to debug. In my code, I have this:

console.log("back from getting updates with "+resp.length + " items to process.");

Try quickly changing it to an alert, rerunning, and tell me if you see a msg? (console.log is nicer, but if you don't know how to see it - this is quicker for you)

Comment 15 by stuart posted on 11/1/2012 at 11:47 AM

executeSql uses an anonymous callback function, the purpose of the callback being that it may take some time before the result is retrieved... so it's possible that displayDocs() is called before all entries are inserted?

Comment 16 by Raymond Camden posted on 11/2/2012 at 12:55 AM

I believe you are right. I would most likely rewrite that logic to make use of jQuery deferreds such that you can say, "When you have done these N asynch ops, then do X", where X is displayDocs.

Comment 17 by Ah Wirayudha posted on 11/9/2012 at 11:23 AM

hai raimond... can i use xui to synch local db and server in phonegap???

Comment 18 by Raymond Camden posted on 11/9/2012 at 5:58 PM

I assume you mean as a replacement for jQuery. If so, yes. I prefer Zepto myself.

Comment 19 by Ah Wirayudha posted on 11/11/2012 at 2:09 PM

any good documentation or tutorial related to this topic??? i mean sync localdb with zepto.. btw.. thanks..

Comment 20 by Raymond Camden posted on 11/11/2012 at 7:20 PM

I'm not sure I understand you. Zepto, like jQuery, is a library of utilities. Zepto is built to be very similar to jQuery. Take a look at the docs and you will see this. A separate demo would't make much sense.

Comment 21 by Ah Wirayudha posted on 11/11/2012 at 9:20 PM

thank you so much... i'm sorry.. cause i'm newbie.. :)

Comment 22 by neeraj Rathore posted on 1/8/2013 at 5:17 PM

i am connecting database using phone gap but it giving error can't access the variable

01-08 16:09:59.350: E/Web Console(326): ReferenceError: Can't find variable: AddValueToDB at file:///android_asset/www/b.html:205

Comment 23 by Raymond Camden posted on 1/9/2013 at 1:23 AM

I'd have to see your code. Is AddValueToDB something you wrote?

Comment 24 by Chris posted on 1/10/2013 at 12:11 AM

Hello,

This is a very helpful article, but I didn't know if there was any easy way to change the server side coding to php? I currently have some php code and would love to integrate this with it. If not, what is the format of the JSON output and I can rebuild a php version? Thanks!

Comment 25 by Raymond Camden posted on 1/10/2013 at 2:51 AM

The JSON can be seen by using the URL I used in the code:

http://www.raymondcamden.co...

Comment 26 by Chris posted on 1/10/2013 at 4:25 AM

Great, thank you. Is there a specific way to generate the token? Or is there a reason it is like this? Thanks again.

Comment 27 by Raymond Camden posted on 1/10/2013 at 7:45 AM

I generated the data like that because - it just made sense. :) There isn't a required reason though.

Comment 28 by Idee posted on 4/4/2013 at 12:05 AM

Waw, thanks for this example

Comment 29 by Akash posted on 5/30/2013 at 3:44 AM

Hello Raymond,
Firstly thank you for this excellent tutorial. I was wondering where the CRUD forms were attached? Sorry as i am unable to find it.
Thank you

Comment 30 by Seema posted on 5/30/2013 at 9:48 PM

Hi Raymond,

I have an app already deployed. I now want to upgrade the app with some schema changes to the existing database. How can I achieve it without losing data from the original database? One way I thought of was creating a new database and copying contents from the original database. I haven't tried it - just an idea.
Please let me know how I can achieve this.
What does db.changeVersion(); do in Phonegap?

Comment 31 by Raymond Camden posted on 5/31/2013 at 2:27 AM

I wouldn't create a new db, I'd just script the table adds. Remember your SQL can do "create table if not exists", so that can be used to safely add the new ones.

Comment 32 by Raymond Camden posted on 5/31/2013 at 2:44 AM

@Akash: Everything should be in the download zip.

Comment 33 by Szymon posted on 8/5/2013 at 5:21 PM

Great article! Thanks for sharing, this really got my to a flying start with what I thought would be a tedious task.
I had to add some operations to go "the other way" as in sending data that has been modified on the device back to the server. I'm sure based on your code anybody can get this done in a few minutes, but still if anybody wants to save a bit of coding, here's my solution:
http://pastebin.com/SUsfahYR

comments welcome, as I am no JS expert ;)
Thanks again for a great article, all the best!

Comment 34 by Raymond Camden posted on 8/6/2013 at 4:12 AM

This is nice, Szymon - thanks for sharing it!

Comment 35 by Alex Lopez posted on 9/30/2013 at 2:44 AM

Hi there, I am getting the error XMLHttpRequest cannot load... localhost ... Origin www.server... is not allowed by Access-Control-Allow-Origin.

Do you know whay I am getting this when tryng to sync from my computer to the server?

Thanks
Alex

Comment 36 by Raymond Camden posted on 9/30/2013 at 7:29 PM

Because web browsers can't make XHR (AJAX) requests to other servers. There are workarounds (CORS, JSON/P), but in general, you are blocked. PhoneGap removed this restriction.

So you need to see if your server supports JSON/P or CORS. You can also try Ripple, but Ripple is a bit rough at the moment.

Comment 37 by Gorkaeff posted on 10/15/2013 at 11:23 PM

Thanks for this example Raymond.
Nowadays, who is the best option to synchronize offline data with my online server in Phonegap?? I've heard something like couchbase but there arent docs about it. I am using Phonegap 3.0 to my example app. Thanks

Comment 38 by Raymond Camden posted on 10/16/2013 at 12:00 AM

Well, I'm not sure I can say what is "best". I spent most of my dev career using ColdFusion, and CF has very good support as a client for XHR requests. You could also use something like Parse.com. (I've done many blog posts on it.)

Comment 39 by Juan Pablo posted on 3/10/2014 at 7:38 PM

I got this (just on the client side, the server side works great, I wrote some docs in there), It doesn't show anything. I need assistance, please.

http://minus.com/i/tInX2G7r...

Comment 40 by Raymond Camden posted on 3/10/2014 at 7:41 PM

Um, you need to be a bit more clear about what is wrong. A screen shot isn't enough.

Comment 41 by Juan Pablo posted on 3/10/2014 at 11:14 PM

The code works exactly the same way as you shared it, with the only difference that uses my localhost, In the server side It works perfectly, with the Doc Editor and everything, I can add content, edit it with no problems, the real issue is on the client side when the app tries to get the documents, it doesn't show neither the table nor the docs.

Comment 42 by Raymond Camden posted on 3/10/2014 at 11:18 PM

Best I can suggest is debugging. Have you tried running the code in a desktop browser?

Comment 43 by Juan Pablo posted on 3/11/2014 at 12:00 AM

Yes, I run the code in Chrome, but still, I can't figure out what's the problem.

Comment 44 by Raymond Camden posted on 3/11/2014 at 12:41 AM

Does it fail the same in Chrome is what I mean? If so - please look into your dev tools to diagnose the issue.

Comment 45 by Gaurav Saini posted on 4/28/2014 at 2:56 PM

Hello,

I am trying to implement synchronization in my app. I am having doubt that when I connect to internet how will my app will know that internet is connected so it can fire sync event in background without opening my application.

Thanks
Gaurav

Comment 46 by Raymond Camden posted on 4/28/2014 at 3:00 PM

You can't, as far as I know. You would have to do the sync next time the user opens the app.

Comment 47 by Gaurav Saini posted on 4/28/2014 at 3:05 PM

Thanks for instant reply Raymond. Do you know any other way to do that in Cordova Apps. As I think this is a necessary thing (as application like gmail, twitter use background sync.)

Comment 48 by Raymond Camden posted on 4/28/2014 at 3:09 PM

Not that I know of. I know there has been some work on 'background plugins' (see the plugins site), but I don't know what state that works is in.

Comment 49 by Terry Collinson posted on 4/28/2014 at 3:41 PM

Not sure how your app will know but the user could be alerted of an update with a push notification

Comment 50 by Bharat Patil posted on 6/24/2014 at 8:20 PM

Post is nice. however I am curious to know what do you think about my solution.

https://www.digitoffee.com/...

I have also added jsfiddle demo in that post.

Comment 51 by Raymond Camden posted on 6/24/2014 at 11:13 PM

Looks nice, Bharat, thanks for sharing it.

Comment 52 by L.e. Nichols posted on 6/27/2014 at 1:51 AM

Script works fine up until populating the noSQL db. Initially it says its inserting but it doesnt. Wondering why? My table is always empty.

Comment 53 by Raymond Camden posted on 6/27/2014 at 6:31 PM

When you debugged, what did you see? Do you see an error in the console?

Comment 54 by L.e. Nichols posted on 6/27/2014 at 11:58 PM

I get this screen. This is my webSQL db: http://i239.photobucket.com...

I get this in my console. Says date is = null.
http://i239.photobucket.com...

Comment 55 by Raymond Camden posted on 6/28/2014 at 9:00 PM

So, it says it is back from getting 28 items. Is resp.forEach running? Maybe on the line after forEach, add console.log("doing an item");

Confirm you see 28 of them.

Comment 56 by L.e. Nichols posted on 6/30/2014 at 5:54 AM

foreach seems to be working but no values in my db: http://i239.photobucket.com...

weird!

Comment 57 by Raymond Camden posted on 6/30/2014 at 5:56 AM

Can you put it online where I can run it?

Comment 58 by L.e. Nichols posted on 6/30/2014 at 7:34 AM

Can i email or inbox you?

Comment 59 by Raymond Camden posted on 6/30/2014 at 7:47 AM

Sure - I'm on vacation this week so may be slow.

Comment 60 by L.e. Nichols posted on 6/30/2014 at 8:36 PM

Ok... i sent you an email with an example and a jsfiddle to have a look at. I can tell its something simple because it gets the values, it just doesnt insert. I've looked at it 100times.

Comment 61 by Senor Felix posted on 7/1/2014 at 10:26 AM

Thanks Raymond for this article. Im a newbie in this and looking for a MySql backend for the DB on a remote server. How would you advice me to customize your setup. Thanks.

Comment 62 by Raymond Camden posted on 7/1/2014 at 7:17 PM

The back end db for this isn't doing anything complete. It's just one table of content. I didn't build a real DB even just used a ColdFusion feature to create a fake query-like object. Maybe if you explain what you tried I can help more.

Comment 63 by Senor Felix posted on 7/1/2014 at 7:23 PM

Thanks for the clarification. I'm actually interested in offline data collection - having the phonegap app work offline, store the data on websql or other html5 storage options and sync the collected data with a MySQL backend on a server. I also want the app to pull some updated tables from the Server and use them as lookups in my data collection form. In a nutshell I'm looking a limited 2-directional syncronization...

Comment 64 by L.E. nichols posted on 7/1/2014 at 7:33 PM

Thanks for your help an reply Raymond I was able to get it working with a few tweets.

Comment 65 by Raymond Camden posted on 7/1/2014 at 7:36 PM

Oh ok - cool. I'm so taking credit even though I didn't do anything. :)

Comment 66 by L.E. Nichols posted on 7/1/2014 at 10:29 PM

Great script btw!

Comment 67 by Jan posted on 8/4/2014 at 3:15 PM

Hi,

how you trigger a function only after the loop which populates the table is finished? I understand each iteration is async, right?

e.g.
for(i=0;i<100;1++){

tx.executeSql("INSERT INTO table1 (id) VALUES (?)",[i]);
}

// do something after everything is inserted

Comment 68 by Raymond Camden posted on 8/4/2014 at 7:29 PM

Use a transaction. Then you can execute code when the entire thing is complete.

Comment 69 by Phillip Senn posted on 8/4/2014 at 8:41 PM

Jan,

I've pasted some code here:
http://jsfiddle.net/Phillip...

This is how I did it a few months ago.
I've since moved to Railo but I hope you can glean some info from looking at how I accomplished the same thing back when.

Comment 70 by Stephan Reinecke posted on 8/6/2014 at 3:01 PM

Thank you for this great article!

I have one problem with the dates (lastupdated):
I rebuild the serverbackend in PHP / MySQL and syncing (insert / update / delete) works fine. But it is *updating all records every time*, though I didn’t make any changes in the serverbackend.

My date format in both db tables and the local storage is 0000-00-00 00:00:00. Is that correct or must it be another format?

Comment 71 by Raymond Camden posted on 8/6/2014 at 6:03 PM

I'd begin by doing some console.logging to see if the time thing is a problem. For example, look at your db value on the client side versus the server. For two values that are supposed to be the same, are they not? And if not, *how* are they different?

Comment 72 by Stephan Reinecke posted on 8/6/2014 at 6:47 PM

Just checked with your original date format (April, 03 2012 15:08:50) and it is the same behavior, it is updating all records, not just the changed ones.
I thought, there is a date comparison to just update records with newer dates.

Doesn't matter. In my real app, I will have only one lastupdate field to sync the whole database or something like that. Thx!

Comment 73 by capa posted on 8/25/2014 at 9:52 AM

Naviagator.connection.type return 0 for cordova 3.5 , Please tell how to solve it??

Comment 74 by Raymond Camden posted on 8/25/2014 at 3:11 PM

What platform?

Comment 75 by Ustym posted on 10/8/2014 at 5:29 PM

I'd like to put your photo on the wall in my rooom.
Really usefull info for beginers like me! Thanks a lot!

Comment 76 by Raymond Camden posted on 10/8/2014 at 6:19 PM

Heh, that's not creepy at all. ;)

Comment 77 by L.E. Nichols posted on 10/12/2014 at 1:11 AM

Whats the best method to redirect after sync is completely finished inserting?

Comment 78 by Raymond Camden posted on 10/13/2014 at 2:38 PM

It depends. If you are using Angular then the $location service makes it simple. jQuery Mobile has a way to load a new view too.

Comment 79 by Gowri posted on 10/17/2014 at 2:12 PM

Thank you for this great article!

But in first time i am seen all data .After that i am delete browse data.After that i cant access data. in console log shows.
Starting up...
table created
DB initialization done.
Will get items after April, 03 2012 15:08:50

and nothing it shoes

Comment 80 by Raymond Camden posted on 10/17/2014 at 2:22 PM

So it says it will get the items but it does not - what does the Network tab show in Dev Tools?

Comment 81 by Gowri posted on 10/17/2014 at 2:36 PM

Here is the code console log shows

"back from getting updates with 0 items to process. "

syncDB();
if(navigator.network && navigator.network.connection.type != Connection.NONE) syncDB();
else displayDocs();
}

function syncDB() {
$("#docs").html("Refreshing documentation...");
console.log("inside");
var date = localStorage["lastdate"]?localStorage["lastdate"]:'';
console.log("Will get items after "+date);
$.get(updateurl, {date:date}, function(resp,code) {
console.log("back from getting updates with "+resp.length + " items to process.");
//Ok, loop through. For each one, we see if it exists, and if so, we update/delete it
//If it doesn't exist, straight insert
resp.forEach(function(ob) {
console.log("we");
db.transaction(function(ctx) {
console.log("back");
ctx.executeSql("select id from docs where token = ?", [ob.token], function(tx,checkres) {
if(checkres.rows.length) {
console.log("possible update/delete");
if(!ob.deleted) {
console.log("updating "+ob.title+ " "+ob.lastupdated);
tx.executeSql("update docs set title=?,body=?,lastupdated=? where token=?", [ob.title,ob.body,ob.lastupdated,ob.token]);
} else {
console.log("deleting "+ob.title+ " "+ob.lastupdated);
tx.executeSql("delete from docs where token = ?", [ob.token]);
}
} else {
//only insert if not deleted
console.log("possible insert");
if(!ob.deleted) {
console.log("inserting "+ob.title+ " "+ob.lastupdated);
tx.executeSql("insert into docs(title,body,lastupdated,token) values(?,?,?,?)", [ob.title,ob.body,ob.lastupdated,ob.token]);
}
}

});
});
});
//if we had anything, last value is most recent
if(resp.length) localStorage["lastdate"] = resp[resp.length-1].lastupdated;
displayDocs();
},"json");

}

Comment 82 by Raymond Camden posted on 10/17/2014 at 2:55 PM

You said you deleted data - did you clear the localStorage value used to mark the date?

Comment 83 by Stephan Reinecke posted on 10/24/2014 at 1:37 PM

I have 5 tables to sync, what is the best solution to get the latest date of update?

For every table I can get the latest date with
if(resp.length) var lastdate = resp[resp.length-1].last_update;

But how can I store them to sort and get the latest? I tried with an array, but I can't get this array out of the sync function (because of ajax?). Do I need a callback and how to do it?

Comment 84 by Raymond Camden posted on 10/25/2014 at 6:50 AM

Why not use the same process for each? They will be asynch but it will work. If you need to ensure ALL have checked and ALL have updated (if need be), look into using Promises to help manage it.

Comment 85 by Eulador posted on 11/6/2014 at 8:54 PM

We need a Windows Mobile app on a Motorola device that will collect data remotely and then sync to an Access db when it is connected to its host PC. Is this a standard feature in the PhoneGap environment or is this always a "do it yourself" solution?

Comment 86 by Raymond Camden posted on 11/6/2014 at 9:29 PM

Well syncing via AJAX is easy - connecting to an Access db on a client machine would need a custom plugin.

Comment 87 (In reply to #39) by mysoftt posted on 6/24/2015 at 8:32 PM

did you solve this problem??