I\'m making a TreePanel that looks like this:
At the moment I have it \"mo
I believe the node
parameter will help you. Set autoLoad: false
, then leverage the beforerender
event of the actual tree panel. Inside the event call the store's load function, and pass it a node
. The docs state that if this is ommited from the load()
call, it will default to the root node. It would appear that you could leave your settings in the root node and then by calling load and passing it a child node, you'd be able to update just the users.
Please see: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.data.TreeStore-method-load for reference. Note that this load function is not the same as in Ext.data.Store
(Ext.data.TreeStore
does not inherit from Ext.data.Store
).
I have not had the opportunity to test this, but it seems promising.
The solution that worked best for me was to:
I wrote up a little tutorial that includes a runnable demo here (in case anyone wants a more detailed answer), but at a high level the code looks like this:
Ext.define('demo.UserModel', {
extend: 'Ext.data.Model',
fields: ['id', 'name', 'profile_image_url']
});
var userTreeStore = Ext.create('Ext.data.TreeStore', {
model: 'demo.UserModel',
proxy: {
type: 'jsonp',
url : 'https://myserver/getusers',
reader: {
type: 'json',
root: 'users'
}
},
listeners: {
// Each demo.UserModel instance will be automatically
// decorated with methods/properties of Ext.data.NodeInterface
// (i.e., a "node"). Whenever a UserModel node is appended
// to the tree, this TreeStore will fire an "append" event.
append: function( thisNode, newChildNode, index, eOpts ) {
// If the node that's being appended isn't a root node, then we can
// assume it's one of our UserModel instances that's been "dressed
// up" as a node
if( !newChildNode.isRoot() ) {
newChildNode.set('leaf', true);
newChildNode.set('text', newChildNode.get('name'));
newChildNode.set('icon', newChildNode.get('profile_image_url'));
}
}
}
});
userTreeStore.setRootNode({
text: 'Users',
leaf: false,
expanded: false // If this were true, the store would load itself
// immediately; we do NOT want that to happen
});
var settingsTreeStore = Ext.create('Ext.data.TreeStore', {
root: {
expanded: true,
children: [
{
text: 'Settings',
leaf: false,
expanded: true,
children: [
{
text: 'System Settings',
leaf: true
},
{
text: 'Appearance',
leaf: true
}
]
}
]
}
});
// Graft our userTreeStore into the settingsTreeStore. Note that the call
// to .expand() is what triggers the userTreeStore to load its data.
settingsTreeStore.getRootNode().appendChild(userTreeStore.getRootNode()).expand();
Ext.create('Ext.tree.Panel', {
title: 'Admin Control Panel',
store: settingsTreeStore,
});
I have a very similar problem, and while I haven't gotten it to work completely like I want it to, it mostly works. I have autoLoad: false
and added this event handler:
beforerender: function(comp, opts) {
var node = this.getRootNode();
node.appendChild({test: 'Recent', id: 'recent', expandable: true, expanded: false});
node.appendChild({text: 'Current', id: 'current', expandable: true, expanded: false});
node.appendChild({text: 'All', id: 'all', expandable: true, expanded: false});
}
The 3 immediate children of the root are static, then the proxy makes a request to populate them when I expand them (passing the appropriate id).
I also had to suppress the root node from loading with a listener on the store:
listeners: {
beforeload: function(store, operation, opts) {
if (operation.node.data.id == 'root') {
return false;
}
}
},
Hope this helps. It seems like there should be a better way!?!
I used a reader to achieve this effect in what I feel to be an elegant fashion. Mind you this is with a flat store and may look a little different with a tree store. The concept should translate.
Ext.define('Ext.data.reader.a8PolicyReader', {
extend: 'Ext.data.reader.Json',
read: function(response) {
var staticStuff,
responseArr;
// Static stuff
staticStuff = [{name: 'some static user', id:1}, {name: 'another user', id:2}];
// extract response
responseArr = Ext.decode(response.responseText);
// shove them together
responseArr.concat(staticStuff);
// read
this.readRecords(responseArr);
}
})
Here is my function to convert normal data to treeStore data, you can use that. By that way, you don't need treeStore anymore:
Records: array of record. Text: name of item (get from record) Children: name of children (default is 'children')
dynamicReportsStore.load({
scope: this,
callback: function (records, operation) {
if (operation.isComplete()) {
var tree = this.buildTreeByRecords(records, 'name');
treePanel.getRootNode().removeAll();
treePanel.getRootNode().appendChild(tree);
}
}
});
buildTreeByRecords: function (records, text, children) {
var childs = [],
results = [],
tree = [];
records = Ext.Array.map(records, function (record) {
return {
text: record.get(text) || record.get('id'),
leaf: record.get('leaf'),
expanded: true,
parentId: record.get('parentId'),
id: record.get('id')
};
}, this);
Ext.each(records, function (record) {
if (Ext.isEmpty(childs[record.parentId])) {
childs[record.parentId] = [];
}
childs[record.parentId].push(record);
}, this);
Ext.each(records, function (record) {
if (!Ext.isEmpty(childs[record.id])) {
record[children || 'children'] = childs[record.id];
results.push(record);
}
}, this);
Ext.each(results, function (result) {
if (result.parentId === 0) {
tree.push(result);
}
}, this);
return tree;}