Sencha Touch 2 Nested List Example using Java Servlets, JSON and MySQL data

A nested list is basically a list of items in a Tree structure. In computer science, a tree is a widely used data structure that simulates a hierarchical tree structure with a set of linked nodes. A tree starts with a root node and each node may or may not have children. Nodes that have one or more children are compared to the Tree branches and if a node doesn't have any children its called a leaf.

Now with Sencha Touch you can use a Tree Store to capture a data stucture similar to that say for example a category drill down for an ecommerce application. All you need to do here is define a nested list and assign a Tree Store as a store for that view. In addition to that you have to specify which field in the model will be the displayed in the list based on the config called displayField. In this example The Tree Store receives the data from a MySQL database using AJAX. The data is formatted in JSON and the service is written using Java Servlet. You can use PHP to send the same JSON data as well.

If you have a small list you can request the complete Tree data in one shot and the nested list will display it but in most cases we would like to get data from the server on demand rather than loading the complete data structure as a JSON object. In this example we load the root level children when we display the list for the first time and then if the user clicks on a list item it goes out and gets more nodes if there is any. If there are no more children available for that node then that item is considered a leaf and we display a detail page based on the item that was clicked. This type of drill down is essential for numerous applications.

Sencha Touch Nested List Example
Sencha Touch Nested List Detail Page

Application starting point - index.html

<!DOCTYPE html>
<html>
<head>
<title>Sencha Touch NestedList Tutorial - Load data from MySQL</title>
<link rel="stylesheet"
 href="sencha-touch/resources/css-debug/sencha-touch.css"
 type="text/css">
<script type="text/javascript"
 src="sencha-touch/sencha-touch-all-debug.js"></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body>
</body>
</html>

Source for JavaScript file - app.js

Ext.Loader.setConfig({ 
 enabled: true 
});

Ext.application({
    
 name: 'MyApp',
 appFolder: 'app',
 
 requires: [
               'MyApp.view.CountryPanel',
               ], 
               
    views : ['CountryPanel'],           
    controllers: ['TheWorld'],
    
    launch: function() {
     console.log('Application launch');
     Ext.create('Ext.Container', {
      fullscreen: true,
      layout: 'vbox',
         items: [{
          flex: 1,
          xtype: 'countryPanel'
            }]
     });
    }
    
});

Source for Model Object - Country.js

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

Source for Tree Store Object - Countries.js

Ext.define('MyApp.store.Countries', {
    extend: 'Ext.data.TreeStore',
    
    config: {
     model: 'MyApp.model.Country',
     proxy: {
         type: 'ajax',
         url: 'CountryServlet',
    }
    }    

});

Source for Nested List View - CountryPanel.js

Ext.define('MyApp.view.CountryPanel', {
    extend: 'Ext.dataview.NestedList',
    alias : 'widget.countryPanel',
    
    config: {
     store : 'Countries',
     title: 'Select your Continent',
        displayField: 'text',
         
     detailCard: {
            html: 'You can see detail information here!'
        } 
    
    } 
});

Source for Application Controller - TheWorld.js

Ext.define('MyApp.controller.TheWorld', {
 extend : 'Ext.app.Controller',
 
 config: {
  profile: Ext.os.deviceType.toLowerCase(),
  stores : ['Countries'],
  models : ['Country'],
  refs: {
   myContainer: 'countryPanel'
  },
        control: {
   'countryPanel': {
             activate: 'onActivate',
             leafitemtap: 'onDetailDisplay'
            }
        }  
  
    },
    
 onActivate: function() {
     console.log('Main container is active');
    },
    
    onDetailDisplay: function(nestedList, list, index, target, record) {
        var detailCard = nestedList.getDetailCard();
        detailCard.setHtml('Here is the detail information for ' + 
          record.get('text'));
    },
    
    onItemTap: function(view, list, index, target, record, event) {
     console.log('Item was tapped on the Data View');
     console.log(view, list, index, target, record, event);
     if(event.target.type == "button"){
      Ext.Msg.alert('You clicked on the Button ...', 
        'The country code selected is: ' + event.target.name);
     }
     else {
      Ext.Msg.alert('You clicked on the Row ...', 
        'The country code selected is: ' + record.get('code'));
     }
     //return false;
    },
    
    init: function() {
     console.log('Controller initialized');
    },
   
});

Click here to view the backend Java Servlet coding

References