My article for Adobe’s Appliness magazine: Loading data into, and posting data from, a PhoneGap app
Filed in: android, apps, Cordova, iOS, jQuery, JSON, MySQL, PhoneGap, php, zepto
In September we tweeted a photo at RITH of a PhoneGap app we’d been working on. The photo showed the app running on quite a few iOS and Android phones and an iPad. One HTML5 app, running perfectly on many devices, all with different resolutions and pixel densities.

Following a retweet by PhoneGap we were contacted by Adobe’s new magazine, Appliness, to see if we’d like to write an article for their October issue. I jumped at the chance.
The editor suggested I base my article around two of my most commented on articles, loading data into and posting data from PhoneGap apps. Rather than just copying and pasting I thought I’d create an actual app to showcase how both techniques can be used.
You can download October’s issue of Appliness on the App Store for iPad and Google Play for Android tablets. But I thought it would be good to have my new article here as well:
Introduction
When I downloaded PhoneGap in 2009 the first thing I wanted to learn was how to load external data from a server or API into an app.
Over the last three years I’ve built several large PhoneGap/Cordova apps that completely rely on data being loaded into and posted from an app. I would like to explore and share the techniques that I use to accomplish these tasks in this article.
All of the code used in this article is available on its own github repository. Each code snippet has its own commit.
App context
For the purpose of this article I’ll use the context of an app which allows users to view and add to a list of code bugs which will then form the framework of a bug tracking app for internal use by a team of developers.
A bug app. Let’s call it BAPP.
BAPP will be an iOS Cordova/PhoneGap app.
App framework
I am going to focus on two functions of this app:
- viewing a list of open bugs
- adding a new bug
If BAPP was a real app there would be additional functions such as user and project management, viewing bug details, actioning bugs and marking bugs as fixed. But for the purposes of this article we’ll focus on the essentials; viewing and adding bugs.
App components
The app will rely on a number of components:
- a PHP/MySQL server environment
- JavaScript ajax calls to the server
- PHP scripts to select open and add new bugs
Setting up a server environment to maintain all of the bugs
Before getting into the app itself I’m going to create a database on a server that will contain a list of all of the bugs we want to track in BAPP. This article isn’t really about server side technologies so I’m going to assume a basic level of knowledge about this.
Creating the bugs database
I’m going to create a new database called bapp, on my local MySQL server, and add the following bugs table:
CREATE TABLE `bugs` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `title` varchar(140) DEFAULT NULL, `details` text, `priority` tinyint(1) DEFAULT '1', `open` tinyint(1) DEFAULT '1', `date_time_added` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
Note: in a real world app you’d have a lot more fields here. But these are all we need for now.
Making a JSONp resource to fetch the open bugs
With the database set up the next thing to do is ensure there is a method of fetching all of the open bugs from the database.
To keep things simple and easy to follow, the PHP script that we’re going to make here will be running on the same server as the database—localhost for me. I’m going to create a directory in my localhost htdocs folder called bapp for this file.
localhost/bapp/bugs.php
<?php
$server = "localhost";
$username = "root";
$password = "";
$database = "bapp";
$con = mysql_connect($server, $username, $password) or die ("Could not connect: " . mysql_error());
mysql_select_db($database, $con);
$sql = "SELECT id, title FROM bugs WHERE open = TRUE ORDER BY priority, date_time_added";
$result = mysql_query($sql) or die ("Query error: " . mysql_error());
$bugs = array();
while($row = mysql_fetch_assoc($result)) {
$bugs[] = $row;
}
echo $_GET['jsoncallback'] . '(' . json_encode($bugs) . ');';
mysql_close($con);
?>
https://github.com/samcroft/bapp/commit/e83964faf3d71820bf6864db89cfa87414129682
The order I am selecting the bugs in is by priority and then the date they were added, so the urgent bugs appear first.
When this PHP script is called it will output the bugs in the following format, forming the JSON object:
[
{
"id": "3",
"title": "Third bug",
"priority": "1",
"date_time_added": "2012-09-27 16:19:05"
},
{
"id": "1",
"title": "First bug",
"priority": "5",
"date_time_added": "2012-09-27 16:18:12"
},
{
"id": "2",
"title": "Second bug",
"priority": "5",
"date_time_added": "2012-09-27 16:18:14"
}
]
Setting up the app
When you have set up your Cordova project you will have a www folder that contains index.html. The first thing we need to do is open up index.html in your text editor of choice and delete the default Cordova HTML body content.
The result of which should be something like between the body tags:
www/index.html
<body> <script src="cordova-2.0.0.js"></script> <script src="js/index.js"></script> <script> app.initialize(); </script> </body>
https://github.com/samcroft/bapp/commit/9ceefb9969ba00882fc1024d9fe8009ac76df188
While I’m at it, I’m also going to completely empty Cordova’s default index.css file.
At this point you could use a mobile framework such as jQuery Mobile, jQTouch or Sencha Touch. But as I’m only going to be using a couple of pages/sections I’m going to keep things simple and just use a tiny bit of CSS to toggle the visibility of two different pages.
The following markup consists of two pages/sections:
www/index.html
<div class="page current" id="bugs"> <header> <h1>Open bugs</h1> </header> <ul></ul> </div> <div class="page" id="add-bug"> <header> <h1>Add a new bug</h1> </header> <form> <label for="bug-title">Bug title</label> <input type="text" id="bug-title" name="bug-title"> <label for="bug-details">Bug details</label> <textarea id="bug-details" name="bug-details" cols="30" rows="10"></textarea> <label for="bug-priority">Bug priority</label> <select id="bug-priority" name="bug-priority"> <option value="1">Urgent</option> <option value="2">High</option> <option value="3">Medium</option> <option value="4">Low</option> </select> <input type="submit" value="Add bug"> </form> </div>
https://github.com/samcroft/bapp/commit/76acbc3891fc998123d38532c672c3effc0ade0f
Here we have added the page for displaying the open bugs and a page with a form for submitting new bugs.
Note: I’m not going to cover how to handle the page / view switching but you can download the entire BAPP project from its github page to see how it works (it’s pretty simple).
Loading the open bugs into the app
So now the database is setup and we have a JSON resource to call from within the app we can get to the main part of this article; dealing with data in an app.
Here I’m going to use Zepto.js to load a JSON data object into the app and append the results to an unordered list into our HTML index file. First I need to include the Zepto library:
www/index.html
<script src="js/zepto.min.js"></script>
https://github.com/samcroft/bapp/commit/e6ffcb8874394b63a5986165c97e1f7ff6fdc227
The reason I’m using Zepto.js rather than jQuery is because it is so much lighter in file size, weighing in at a paltry 24kb (when using the minified version). jQuery itself is an enormous library containing a great many features that you wouldn’t ordinarily be leveraging in an app. That’s a lot of unnecessary bloat. Zepto on the other hand is like all of the functions from jQuery that you would likely be using in an app, plus a handy (no pun intended) array of touch events.
If you’re more comfortable with jQuery, that’s ok, the JavaScript in this article remains the same, it’s just the include that is different. I do, however, use a tap event in the final build of BAPP that you download from its github page, so be aware of that if you do use jQuery.
When the app is opened it’s going to automatically load the open bugs from the database and place them in the unordered list in the first page. This can be accomplished by using Zepto’s ajax() function.
Using Zepto’s .ajax() function to create a basic data request
Almost all of the Cordova/PhoneGap apps I’ve built have used the .ajax() function extensively. A basic ajax() function setup, to load data, might look like this:
$.ajax({
type: 'GET',
url: 'http://your-server.com/your-resource.php',
dataType: 'JSON',
success: function(data) {
//do something with the data
},
error: function(data) }
//do something if there is an error
}
});
Here we’d be using a GET request to access a server resource and expecting to receive back a JSON object. If it’s successful we can do something with the loaded data. If there is an error we can display an appropriate message.
Within BAPP we’re dealing with a JSON data object. But more specifically, JSONp. JSONp is used to load JSON data from a different server/location to where the data is hosted. And while cross-domain concerns aren’t much of a worry with a Cordova/PhoneGap app, as it uses the file protocol. Using JSONp requests means that you’re building a web app that isn’t constrained to running in Cordova’s environment. While you might not necessarily be releasing your app as a mobile browser app, you will almost certainly be spending hours debugging it in your favourite webkit browser. You’re going to want to build things with cross-domain access in mind.
So with that out of the way, we just need to make a few tweaks to the basic .ajax() function above, for use in BAPP, to load those glorious bugs. I’m going to add this request in the default index.js file that Cordova makes for you. I’m also going to place this ajax request in its own function so that we can call it when we want:
www/js/index.js
function loadBugs() {
var bugs = $('#bugs ul');
$.ajax({
type: 'GET',
url: 'http://localhost/bapp/bugs.php?&jsoncallback=?',
dataType: 'JSONp',
timeout: 5000,
success: function(data) {
$.each(data, function(i,item){
bugs.append('<li>'+item.title)
});
},
error: function(data) {
bugs.append('<li>There was an error loading the bugs');
}
});
}
loadBugs();
https://github.com/samcroft/bapp/commit/509061f3cf240d699781bc2d0db8a1e8e8d49d5e
This will make a request to the server that has the bugs.php file which, in turn, selects the bugs from the database, encodes the records as JSON and then returns it to the function invoked via the success property of the ajax function.
The most important aspect in this particular ajax request is the callback parameter in the url string. This is what makes the JSONp request function correctly. Without this parameter, the request will fail. The callback parameter appends an automatically generated string to the requested url which is then returned, wrapping around the JSON object. You can call the callback parameter anything you like, but you must reference the same name in your PHP script (see above).
Note: with jQuery, you can add the callback parameter as a property of the ajax function itself, rather than appended to the url string.
Once we have the JSON object passed to the success callback function in the ajax() function, it’s just a case of looping through each of the bugs and appending the relevant details to the unordered list we created in the index.html file. Zepto’s .each() function makes that a breeze.
The PHP script has already ensured that the bugs will appear in the correct order so all that is required is to append each bug to the unordered list we created earlier.
Testing this in the browser should load the list of bugs. If the error message is displayed then you should check your JavaScript console and see what kind of error is being thrown. If it’s syntax related it will most likely be a code issue with how things have been set up. If it’s showing an error code, check the network tab to see whether or not the JSON resource is actually being called. You should be able to diagnose any issues from here.
Finally, before building the Cordova app and running in the simulator, or on your device, you will need to whitelist the server that you are connecting to pull the data from. Using my example you will need to add localhost as an ExternalHost in Cordova.plist. This is Cordova’s method of ensuring that you only pull data from websites that you have explicitly mentioned you will be interacting with.
Running BAPP should now produce a lovely list of bugs. Beautiful bugs. That is, if we had some in the bugs database! Right now it’s empty, so let’s go to the next section to add some bugs.
Adding a new bug and posting it to the server database
The second part of this article concerns posting data from an app to a server. Here are the steps I’m going to go through:
- use Zepto’s submit event handler to grab the new bug information
- use Zepto’s ajax function to send the data to the server
- create a PHP script to receive the data and store it in the database
The form
I added the form markup right at the start of this article, let’s look at it again:
<form> <label for="bug-title">Bug title</label> <input type="text" id="bug-title" name="bug-title"> <label for="bug-details">Bug details</label> <textarea id="bug-details" name="bug-details" cols="30" rows="10"></textarea> <label for="bug-priority">Bug priority</label> <select id="bug-priority" name="bug-priority"> <option value="1">Urgent</option> <option value="2">High</option> <option value="3">Medium</option> <option value="4">Low</option> </select> <input type="submit" value="Add bug"> </form>
Here we just have three fields; the bug title (text input), bug details (textarea) and the bug priority (select menu). Although I’m not using the bug-details field or data anywhere else in the app, I thought it was good to leave it in to show how handling multiple fields is relatively easy.
Using the ajax() function to grab the form data and send it to the server
Here I’m going to use the ajax() function again but this time to POST data rather than load it. While the basic setup of the ajax function is the same, it requires an additional parameter, data, where the form data is supplied:
www/js/index.js
$('#add-bug form').submit(function(){
var postData = $(this).serialize();
$.ajax({
type: 'POST',
data: postData,
url: 'http://localhost/bapp/add-bug.php',
success: function(data){
console.log('Bug added!');
},
error: function(){
console.log('There was an error');
}
});
return false;
});
https://github.com/samcroft/bapp/commit/eaab3f668eb43dcb8bc04b3717d6f2f2bc727553
Here I’m using the submit event that starts a function that collects the form data, via the serialize() method and then calling a new ajax() function where the type is set to POST and a parameter called data is given the serialised data.
The serialize() method goes through all the form fields and collects their respective values. It makes it easier than selecting the values one by one.
For now I’ll leave the success function empty and come back to that after detailing the PHP script that’s going to receive this POST’ed data.
Creating a PHP script to handle and store the bugs
The next part of submitting a bug is to create a PHP script that takes the data from the app and stores it in the MySQL database we created right at the start.
localhost/bapp/add-bug.php
<?php
$server = "localhost";
$username = "root";
$password = "";
$database = "bapp";
$con = mysql_connect($server, $username, $password) or die ("Could not connect: " . mysql_error());
mysql_select_db($database, $con);
$bugTitle = mysql_real_escape_string($_POST["bug-title"]);
$bugDetails = mysql_real_escape_string($_POST["bug-details"]);
$bugPriority = mysql_real_escape_string($_POST["bug-priority"]);
$sql = "INSERT INTO bugs (title, details, priority) ";
$sql .= "VALUES ('$bugTitle', '$bugDetails', $bugPriority)";
if (!mysql_query($sql, $con)) {
die('Error: ' . mysql_error());
} else {
echo "Bug added";
}
mysql_close($con);
?>
https://github.com/samcroft/bapp/commit/aa57a2ae75e9dcea2ada97453e93c2ee1f1dde64
This connects to our MySQL server, with the same connection strings as the previous script, and selects the bugs database.
Next I need to get the bug details that have been submitted from the app. In the previous step I used Zepto’s serialize function to make things a bit easier client side. To get the values into our PHP script we need to use PHP’s $_POST variable. The $_POST variable is an array that contains keys and values of data that has been sent to the PHP script via the POST method. The key is the name of the form field and the value is… it’s value. Therefore to obtain the bug title we need to use the key bug-title and for the bug details the key bug-details.
One other thing I’m doing here is using MySQL’s mysql_real_escape_string function to strip the values of any malicious code that could have been submitted via the app. Note that to use mysql_real_escape_string, you must call it after you have connected to MySQL.
Next I’m just executing a simple INSERT sql statement.
Providing your code is error free this will insert the new bug into the database.
Now you can add bugs and view the current open bugs.
Note: these screenshots have CSS applied that I have not covered in this article. The CSS is included in the projected on github, however.
While BAPP just covers the basics, a real world instance of this app might allow you to tap each bug to view more details. And then action the bug, give comments, add a status and of course – mark it as closed.
Finishing touches
That completes all of the server side code for this app. The final step is just to add a few checks to the submit function written earlier.
Expected behaviour would be that after you have submitted a bug you are taken back to the open bug list where it is refreshed, with the newly added bug visible.
Revisiting the submit event
$('#add-bug form').submit(function(){
var loading = $(this).find('input[type="submit"]');
loading.addClass('loading');
var postData = $(this).serialize();
$.ajax({
type: 'POST',
data: postData,
url: 'http://localhost/bapp/add-bug.php',
success: function(data){
loadBugs();
$('#bugs').addClass('current');
$('#add-bug').removeClass('current');
loading.removeClass('loading');
console.log('Bug added!');
},
error: function(){
loading.removeClass('loading');
console.log('There was an error');
}
});
return false;
});
https://github.com/samcroft/bapp/commit/90287ba388d3871a50790e18d16aaafa1954eac0
To do this, we just need to switch page views and call the bug list fetch function written earlier. I’m also going to add a loading indicator while the form is being submitted and data sent to the server.
Finally I’m going to tweak the loadBugs function so that when it is called it first of all empties the list before making the ajax call to the server:
var bugs = $('#bugs ul').empty();
https://github.com/samcroft/bapp/commit/909ff6238194336eb89fa57f6ce16b1bc2024488
Note: if BAPP was a real-world app, there would be more efficient ways of accomplishing this. You could append the newly created bug to the existing list without making an ajax call.
Testing the app
With all of the pieces in place, it’s just a case of testing the app. There are a few things to be aware of here regarding how you test the app.
Testing in a browser
If you’re loading the index.html file in your browser you need to be aware that depending on where the file is located and how you are opening it will affect the POST ajax call. Simply opening index.html in a browser will cause the POST ajax call to fail, as it is not running on a server. To test the file in a browser you will need to run it on a server, either locally on your machine or a domain you have access to.
This does not apply to the the GET ajax call, however, providing the PHP script is running on a server somewhere.
If you have downloaded the entire project from github and want to test it in your browser you will also need to change the tap event, on line 72 of www/js/index.js, to a click event.
Testing in the iPhone simulator or on a device
Of course, testing in XCode and the iPhone simulator, you won’t run into any of the above issues. There is one thing to be aware of though, regarding Zepto/jQuery. Ordinarily you’d wait until the DOM was ready before including your JavaScript. With Cordova, however, we need to wait until Cordova is ready, which occurs after the DOM is ready. Waiting for Cordova to be ready means that you can use Cordova’s API to make use of various device and native functionality.
To do this we can just change the normal DOM check:
$(document).ready(function(){
//your code
});
…to:
$(document).on('deviceready', function() {
//your code
});
https://github.com/samcroft/bapp/commit/570e0d2ba7186f71c00868043e7602a0af081b2c
The latter method is of course how you should have things set up if you were building BAPP for release.
Final notes
I’ve tried to keep on topic by deliberately not mentioning anything about CSS and how BAPP might look – that’s not really what this article is about. I have, however, added some basic CSS to BAPP if you download the project.
You can download all of the source code and the Cordova iOS project through a github repository for BAPP – https://github.com/samcroft/bapp – each code snippet above has its own commit.



Pingback: Phonegap Tutorials « PHPsolutionBD