Dynamically Loading Ext.NestedList

After developing the USGS earthquake for mobile, I want to extend it to display more information. One of the challenge I faced was how to dynamically load data into the nested list. I did a bit reading in the forum and someone suggested to implement the following.

var nestedList = new Ext.NestedList({
items: []
});

var list = [
{
text: 'Test'
},{
text: 'Test 2'
}];

nestedList.setList(list, true);

I did try out to use setList(), however I noticed a problem when I clicked the back button. The nested list still remember the original “items” which was set to blank or []. It is correct that setList() will rebuild the entire list, however in this instance it is not the right method to use. One thing to highlight is the setList() is called when item is tapped and when we click back button, however everytime it is called the new list is appended to the end of the collection as shown in the code below. As we tap the item and click back, the index counter become wrong.

if (!this.lists.contains(list)) {
this.lists.push(this.add(list));
}

I will cover 2 scenarios related to this topic:

  1. Dynamically load nested list after the UI is launched.
  2. Dynamically load list when item is tapped.

The alternative solution to dynamically set the nested list is to extend the original object and implement a new method “reset” as shown below. Perform exactly as It is in setList() but instead of joining the list, reset it. This will address scenario 1.

Ext.ws.NestedList = Ext.extend(Ext.NestedList, {
resetList : function(list, init) {
//...
if (!this.lists.contains(list)) {
this.lists[0] = this.add(list);
}
//...
},

onItemTap : function(item) {
//...
}
});

In order to address scenario 2, override the onItemTap() as shown below. In this example, I added a new attribute “fid” into the item which helps to decide what data to load. In your implementation you might call JSONP request to load the data.

Ext.ws.NestedList = Ext.extend(Ext.NestedList, {
resetList : function(list, init) {
//...
},

onItemTap : function(item) {
item.el.radioClass('x-item-selected');
if (item.items) {
this.backButton.show();
if (item.fid == 'A') item.items = [ {text: 'List Z.1'} ];
this.setList(item);
this.listIndex++;
}
this.fireEvent('listchange', this, item);
}
});

The following is the full source code used to demonstrate the 2 scenarios. If you have alternative solution to the above, do drop me comment and share it. 🙂

<script type="text/javascript">

Ext.ns('Ext.ws');

Ext.ws.NestedList = Ext.extend(Ext.NestedList, {
resetList : function(list, init) {
var items = init ? list : list.items;
if (!list.isList) {
list = new Ext.Container({
isList: true,
baseCls: 'x-list',
cls: 'x-list-flat',
defaults: {
xtype: 'button',
baseCls: 'x-list-item',
pressedCls: 'x-item-pressed',
ui: null,
pressedDelay: true
},
listeners: {
afterrender: function() {
this.getContentTarget().addClass('x-list-parent');
}
},
scroll: 'vertical',
items: items,
text: list.text
});
}

this.lists = this.lists || [];
if (!this.lists.contains(list)) {
this.lists[0] = this.add(list);
}

var isBack = (this.lists.indexOf(list) < this.lists.indexOf(this.activeItem));
if (this.rendered) {
this.setCard(list, init ? false : {
type: this.animation,
reverse: isBack
});
}
this.activeItem = list;
},

onItemTap : function(item) {
item.el.radioClass('x-item-selected');
if (item.items) {
this.backButton.show();
if (item.fid == 'A') item.items = [ {text: 'List Z.1'} ];
this.setList(item);
this.listIndex++;
}
this.fireEvent('listchange', this, item);
}
});

Ext.setup({
onReady: function() {

var list = [ {text: 'List A', fid: 'A', items: [] },
{text: 'List B', fid: 'B', items: [ {text: 'List B.1'} ] },
{text: 'List C', fid: 'C', items: [ {text: 'List C.1'} ] }
];

var nestedList = new Ext.ws.NestedList({
items: [],
fullscreen: true
});

nestedList.resetList(list, true);

} // end onReady
}); // end ext.setup

</script>

Update: the example above was based on Sencha Touch 0.91

Advertisements