PDA

View Full Version : How to Create Tree Panel from a dynamic data source



mgarn
28 Dec 2010, 10:14 AM
I am very new to Ext JS and this is the first time I have ever created a post on a forum. I apologize if I say things wrong or sound dumb.

I have the below TreePanel working in my page (I took this from one of the examples on the Ext JS site and made some modifications). my issue now is that I need to replace the static dataUrl reference to the static JSON file with a dynamic data source. If I understand correctly that should be a store of some sort.

Current code:



var

fieldTreeList = new Ext.tree.TreePanel({

title : 'Maint History Field Selection',
id : 'fieldNameID',
height : 200,
width : 200,
autoScroll : true,
animate : true,
enableDD : false,
containerScroll : true,
rootVisible : false,
frame : true,
collapsible : false,
collapsed : false,
header : false,
root : {
nodeType: 'async'
},


// store: HistProcSearch.fieldNameStore,
// auto create TreeLoader
dataUrl :


'js/treeData.json',


listeners: {
'checkchange': function(node, checked){


//WHEN THE TREEE IS FIRST RENDERED THE HIDDEN CHILDREN DO NOT
//APPEAR TO RENDER UNTIL THEY ARE EXPANDED. THUS CASCADING CHECKS
//DO NOT CASCADE. THE BELOW CHUNCK OF CODE EXPOSES ALL THE CHILDREN
if( node.isExpandable() && !node.isExpanded() )
{
node.expand();
node.collapse();
}


//CHANGE LOOK OF TEXT
if( checked )
{
node.getUI().addClass('SelectedItem');


if( node.parentNode.text != "Categories" )
{
node.parentNode.getUI().addClass('SelectedItem');
fieldTreeList.suspendEvents(false);
node.parentNode.getUI().toggleCheck(checked);
fieldTreeList.resumeEvents();
}
}
else
{
node.getUI().removeClass('SelectedItem');


//GET PARENT NODE
var p = node.parentNode;


//CHECK TO SEE IF ANY CHILDREN ARE STILL CHECK
//BEFORE UNCHECKING PARENT
var pChecked = 'N';
if( p.hasChildNodes() )
{
p.eachChild(function(n){
if( n.getUI().isChecked() )
pChecked = 'Y';
})
}


if( pChecked == 'N' )
{
node.parentNode.getUI().removeClass('SelectedItem');
fieldTreeList.suspendEvents(false);
node.parentNode.getUI().toggleCheck(checked);
fieldTreeList.resumeEvents();
}
}


//SET CHILDREN SAME AS PARENT
if( node.hasChildNodes() )
{
node.eachChild(function(n){
n.getUI().toggleCheck(checked);
})
}
}
}
});


The above TreePanel uses a static file with a JSON object in it. A piece of that JSON object is below




[
{
text : 'Categories',
checked : true,
cls : 'SelectedItem',
expanded : true,
singleClickExpand : true,
children : [
{
text : 'ACCOUNT',
checked : true,
cls : 'SelectedItem',
singleClickExpand : true,
children : [
{
text : 'Minimum Pay Amount',
leaf : true,
cls : 'SelectedItem',
checked : true
},
{
text : 'Online Balance',
leaf : true,
cls : 'SelectedItem',
checked : true
},
{
text : 'Maximum Withdrawl',
leaf : true,
cls : 'SelectedItem',
checked : true
}
]
}

]
}
]



I don't understand how to create a datastore. It needs to call a web service and then put that objects returned in JSON format before returning to the TreePanel. I have been looking at the below store example being used for a combobox, but I am not understanding how to modify it to work for a TreePanel.




HistProcSearch.categoryStore = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({
url: HistProcSearch.contextPath + '/maintcatlist.do',
method: 'post'

}),
reader: new Ext.data.JsonReader({
fields: [
{name: 'code', mapping: 'code'},
{name: 'desc', mapping: 'code'}
],
id: 'code',
root: 'maintCatList'

})
});


What I have gathered from the above store example is that the proxy portion makes the request and recieves a response from the URL (web service). The reader takes the response and and parses it maping the code attribute of the "maintCatList" java object to the attributes of the combobox. Am I right and what do I need to do to change this so that it will work for a TreePanel or is there a better way? I am planning on having an object with an embedded ArrayList of objects. This structure will give me my folder and leaf structure.

If someone could help me understand this I would appreciate it. Thank you

Condor
28 Dec 2010, 12:44 PM
No, stores contain flat data and can't be used for trees.

Your server should be able to create the same JSON as the static data.

Remember that if you don't specify children or leaf:true, expanding that node will do another server request with that node id as parameter to retrieve the nested nodes.

mgarn
29 Dec 2010, 1:20 PM
No, stores contain flat data and can't be used for trees.

Your server should be able to create the same JSON as the static data.

Remember that if you don't specify children or leaf:true, expanding that node will do another server request with that node id as parameter to retrieve the nested nodes.


Thank you Condor!

My TreePanel is still not populating so I was able to print out the response which is in JSON format. Now the problem I am having appears to be that the TreeLoader does not like the container the JSON string is in.

{"maintCatList":[..<JSON formatted data>..],"success":true}

If I take the response from the web service call and put it in a static file, then strip off the '{"maintCatList":' at the beginning and the ',"success":true}' at the end the TreePanel populates.

Is there a mechanism to have the TreeLoader ignore the "maintCatList" object and just use the contents in the [...] or do I have to figureout how to make my server not send that portion back?

mgarn
29 Dec 2010, 2:00 PM
I went ahead and just intercepted the JSON object and stripped off the beginning and ending parts that were causing problems and now the TreePanel is populating.

Thanks for pointing me in the right direction Condor!

Condor
29 Dec 2010, 11:49 PM
Supporting a 'root' config option for TreeLoader is a long-standing feature request.

Now you have to override handleResponse to do this, e.g.

loader: new Ext.tree.TreeLoader({
...
handleResponse: function(response) {
response.responseData = Ext.decode(response.responseText).maintCatList;
this.constructor.prototype.handleResponse.call(this, response);
}
})

mgarn
30 Dec 2010, 2:29 PM
Thanks a lot for the work around. I like this better than my solution. You're awesome Condor!

Thanks for your time!