Mobile Zone is brought to you in partnership with:

Jorge is the author of three software development books: "Building a Sencha Touch Application", "How to Build a jQuery Mobile Application", and the "Ext JS 3.0 Cookbook". He runs a software development and developer education shop that focuses on mobile, web and desktop technologies. Jorge is a DZone MVB and is not an employee of DZone and has posted 50 posts at DZone. You can read more from them at their website. View Full User Profile

Creating a Sencha Touch Nested List with a PHP Backend

06.25.2013
| 5975 views |
  • submit to reddit

In this tutorial you will learn how to use a Sencha Touch Nested List to render data sent from a server. I have seen developers who are getting started with Sencha Touch struggle with this scenario, in part because there is little documentation on how to connect a Nested List component to a server endpoint.

The application you will create in this tutorial is very similar to the Nested List example in Sencha’s documentation. The difference is that instead of using local hard-coded data to populate the Nested List, you will create a server-side handler that will supply the data for the list.

Sencha Touch NestedList


Let’s start setting up your sample application. You can either use Sencha Cmd, or manually create the following directories structure for the app:

Nested List app directories

In the index.html file you will add the references to the Sencha Touch framework and the app’s main JavaScript file:

Nested List app index file

Defining the Model

Now you can start working on the app’s components. First, you will create the Grocery.js file in the app/model directory. In the file, you will define the Grocery Model like so:

Ext.define('App.model.Grocery', {
extend: 'Ext.data.Model',
config: {
  fields: [{
    name: 'text',
     type: 'string'
   }]
  }
});

To keep the example as simple as possible, you will use a model with only one field, text, which you will render inside each item of the list.

Creating a TreeStore

Then you will create the Groceries.js file in the app/store directory. This is where you will define the Groceries store. The store’s code should look like this:

Ext.define('App.store.Groceries', {
    extend: 'Ext.data.TreeStore',
    config: {
        model: 'App.model.Grocery',
        defaultRootProperty: 'items',
        proxy: {
            type: 'ajax',
            url: '../../services/groceries.php'
        },
        autoLoad: true,
        root: {
            text:'Groceries'
        }
    }
});

Three important things to note in the store’s definition:

  • The store is a Ext.data.TreeStore, a great place to keep data that is hierarchical in nature.
  • The defaultRootProperty config, which you use to specify a default root property when you don’t explicitly define an XML reader for the store. This is what tells the store the exact place where it can find its data inside the XML document sent by the server.
  • The use of an Ajax proxy, pointing to the server page that will supply the data for the store.

Defining the Nested List

Going back to the app’s components, in the app/view directory you will create the GroceriesList.js file. This is where the GroceriesList class goes:

Ext.define('App.view.GroceriesList', {
    extend: 'Ext.NestedList',
    alias: "widget.grocerieslist",
    config: {
        fullscreen: true,
        title: 'Groceries',
        displayField: 'text',
        store: 'Groceries'
    }
});

GroceriesList is a NestedList component that will use the text field of the Grocery model as its display field, and the Groceries store as its data supplier.

The Application Instance

With these components in place, you can define the application in the app.js file, just like this:

Ext.application({
    name: 'App',
    views: ['GroceriesList'],
    models:['Grocery'],
    stores:['Groceries'],
    launch: function () {

        Ext.Viewport.add([
            { xtype: 'grocerieslist' }
        ]);
    }
});

The application instance itself is pretty simple, after declaring the model, store and view, you use the launch function to create an instance of the GroceriesList component and bring it to the foreground.

Creating the Server Endpoint

The server endpoint is probably the most interesting part of this project. For this example you will use a php page as the endpoint. You will name it groceries.php, and in it you will add the following elements.

First, you will create a class to represent a grocery item:

class GroceryItem {
	function __construct($text, $leaf, $items) {
		$this->text = $text;
		$this->leaf = $leaf;
		$this->items = $items;
	}
}

Next, you will create a class to represent your groceries list:

class Groceries {
	function __construct($items) {
		$this->items = $items;
	}
}

Then you will create a sample groceries list like so:

$redBull = new GroceryItem("Red Bull", true);
$coke = new GroceryItem("Coke", true);
$dietCoke = new GroceryItem("Diet Coke", true);

$espresso = new GroceryItem("Espresso", true);
$coffee = new GroceryItem("Coffee", true);

$stillWater = new GroceryItem("Still", true);
$sparklingWater = new GroceryItem("Sparkling", true);
$water = new GroceryItem("Water", false, array($sparklingWater,$stillWater));
$drinks = new GroceryItem("Drinks", false, array($water,$coffee,$espresso,$redBull,$coke,$dietCoke));

$groceries = new Groceries($drinks);

Note that if this was a production app, this is the place where you would retrieve your groceries from a database, and then populate the list.

After this step, you just need to send the list to the Sencha Touch app:

header('Cache-Control: no-cache, must-revalidate');
header("content-type:application/json");
echo(json_encode($groceries));

And this is all it takes to connect a Sencha Touch Nested List component to a server endpoint. If you run this app, you should see the groceries list working as expected.

Want To Learn More?

My Sencha Touch and jQuery Mobile books will guide you, step by step, through the process of building a Sencha Touch and jQuery Mobile applications. If you like to learn by doing, these books are for you.


Published at DZone with permission of Jorge Ramon, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)