Hi everyone!
When I was trying to use TreePanel, I needed some extra works about parsing of dynamic tree data. I'm using JSON that created with PHP. But I wanted to change structure of TreeNode attributes. For example, I don't like send a "leaf" attributes because of I already knew "children" attribute.
So, I implemented a small plugin named JsonTreeLoader. Maybe somebody needs a plugin like this.
Plugin code:
Code:
Ext.ns('Ext.ux.tree');
/**
* @class Ext.ux.tree.JsonTreeLoader
* @extends Ext.tree.TreeLoader
* <p>A TreeLoader that gives chance to specify a root path of data source, change node attributes
* names.</p>
*
* Creates a new JsonTreeloader.
* @param {Object} config A config object containing config properties.
* @author Murat Corlu
* @link http://muratcorlu.com
*/
Ext.ux.tree.JsonTreeLoader = Ext.extend(Ext.tree.TreeLoader, {
// Nodes array root path
root:undefined,
// To specify different attribute names for TreeNode
attrNames:{},
// You don't have to send a leaf attribute. If your node has children, leaf is false, otherwise true
// You can set this property false to use standart way
leafFromChildrenCount: true,
// private. to handle children attribute name
childrenAttrName: 'children',
// private override
processResponse : function(response, node, callback){
var data = Ext.decode(response.responseText);
// if root property set then use given path as root
if (this.root) {
var rootPath = this.root.split('.');
Ext.each(rootPath, function(path) {
data = data[path];
});
}
// get custom children attribute name
for(customName in this.attrNames) {
if (this.attrNames[customName] = 'children') {
this.childrenAttrName = customName;
}
}
try{
node.beginUpdate();
node.appendChild(this.parseData(data));
node.endUpdate();
if(typeof callback == "function"){
callback(this, node);
}
}catch(e){
this.handleFailure(response);
}
},
// private
parseData : function(data) {
var nodes = [];
Ext.each(data, function(n){
var treeNode = this.createNode(n);
if(n[this.childrenAttrName]){
var child = this.parseData(n[this.childrenAttrName]);
treeNode.appendChild(child);
}
nodes.push(treeNode);
}, this);
return nodes;
},
// private override
createNode : function(node){
this.defaultProcessAttributes(node);
// Make optional manipulations if it set
this.processAttributes(node);
return Ext.ux.tree.JsonTreeLoader.superclass.createNode.call(this, node);
},
defaultProcessAttributes : function(attr) {
// Replace custom attributes with standart ones
for(item in attr) {
if (this.attrNames[item]) {
attr[this.attrNames[item]] = attr[item];
attr[item] = undefined;
}
}
// Automatic leaf calculation
if(this.leafFromChildrenCount) {
attr.leaf = attr.children ? !(attr.children.length > 0) : true;
}
},
// override this method if you want
processAttributes : Ext.emptyFn
});
Usage:
An example of sent data from PHP:
Code:
{
"success":true,
"data": [{ // I can use treenodes array at different path from root
"id":12,
"textData":"First Item", // I used textData key instead of text
"items":[{ // I used items key instead of children
"id":2312,
"textData":"Leaf Item" // I don't have to use leaf key
}]
}]
}
And Ext side:
Code:
new Ext.tree.TreePanel({
........
loader: new Ext.ux.tree.JsonTreeLoader({
dataUrl:"http://example.com/api/",
root:'data', // Setting rootpath
attrNames:{
'textData':'text', // I say: use "textData" for "text"
'items':'children' // and use "items" instead of "children"
}
}),
.......
I hope it will help you...