PDA

View Full Version : Silent Root Reload/Refresh



MrSparks
13 Sep 2010, 2:27 PM
Is it possible to silently reload the root node of a TreePanel?

i.e. I would like to stop the visible refresh of the tree nodes when a reload is called.


mytree.getRootNode().reload(); I have seen something similar on other Tree implementations. DHTMLX call it refresh with (smart mode)


I can't find any examples or docs on how to do this in EXT, so this might be a feature request.....


Many Thanks
MrSparks

Condor
14 Sep 2010, 12:45 AM
Unfortunately, TreePanel can't do this.

You will have to make your own Ext.Ajax.request and update the nodes (setText etc.) with the response.

MrSparks
14 Sep 2010, 3:27 AM
Unfortunately, TreePanel can't do this.

You will have to make your own Ext.Ajax.request and update the nodes (setText etc.) with the response.

@Condor

A custom Ext.Ajax.request is a little too advanced for me at this stage. Will add it to the to'do list. :)

Do you think this would be suitable as a feature request to EXT JS Dev team? Seems to me, a function like this would be in great demand!?

Condor
14 Sep 2010, 4:02 AM
No, its not requested often. Even for a GridPanel most people seem consent with just reloading the store (and thereby refreshing the entire grid).

ps. Does your server return all nodes and children in one request? In that case there are ways to persist the current expanded and selection state of nodes when reloading. You will still see a visual refresh, but it will look identical after that.

MrSparks
14 Sep 2010, 4:20 AM
No, its not requested often. Even for a GridPanel most people seem consent with just reloading the store (and thereby refreshing the entire grid).

ps. Does your server return all nodes and children in one request? In that case there are ways to persist the current expanded and selection state of nodes when reloading. You will still see a visual refresh, but it will look identical after that.

Yes, the server returns a complete set of nodes and children in one go (refined based on user input) but still a complete set. I really like the idea of being able to persist the expanded /selection state. :) Could you point me in the right direction? Thanks!

Condor
14 Sep 2010, 5:44 AM
Try this:

// Configure loader to expand and select previously selected/expanded nodes
var selected, expanded;
var loader = new Ext.tree.TreeLoader({
...
preloadChildren: true,
createNode: function(attrs) {
if (expanded && expanded[attrs.id]) {
attrs.expanded = true;
}
this.constructor.prototype.createNode.call(this, attrs);
},
listeners: {
load: function(loader, node) {
var tree = node.getOwnerTree();
var selModel = tree.getSelectionModel();
if (Ext.isArray(selected)) {
for (var i = 0; i < selected.length; i++) {
var node = tree.getNodeById(selected[i].id);
selModel.select(node);
}
} else if (selected) {
var node = tree.getNodeById(selected.id);
selModel.select(node);
}
}
}
});

// Gather selected and expanded states
var selModel = tree.getSelectionModel();
selected = selModel.getSelectedNodes ? selModel.getSelectedNodes() : selModel.getSelectedNode();
expanded = {};
tree.getRootNode().cascade(function(n){
if (n.expanded) {
expanded[n.id] = true;
}
});
tree.getRootNode().reload();
Disclaimer: Completely untested code!

MrSparks
14 Sep 2010, 8:15 AM
Try this:

Disclaimer: Completely untested code!

Wow thank you! B)

I'm getting this error unfortunately.

node is undefined
node.ownerTree = this;
ext-al...ents.js (line 49905)

Which is in this section of the ext-all.js


49904 this.root = node;
49905 node.ownerTree = this;
49906 node.isRoot = true;
49907 this.registerNode(node);
49908 if(!this.rootVisible){
49909 var uiP = node.attributes.uiProvider;
49910 node.ui = uiP ? new uiP(node) : new Ext.tree.RootTreeNodeUI(node);

MrSparks
15 Sep 2010, 2:15 AM
@Condor

I've isolated the issue to this area of the code. i.e. if I comment it out, the error is no longer present.


// Configure loader to expand and select previously selected/expanded nodes
var selected, expanded;
var loader = new Ext.tree.TreeLoader({
dataUrl: '/pages/west/act_get_tree_data.cfm',
preloadChildren: true,
createNode: function(attrs) {
if (expanded && expanded[attrs.id]) {
attrs.expanded = true;
}
this.constructor.prototype.createNode.call(this, attrs);
},
listeners: {
load: function(loader, node) {
var tree = node.getOwnerTree();
var selModel = tree.getSelectionModel();
if (Ext.isArray(selected)) {
for (var i = 0; i < selected.length; i++) {
var node = tree.getNodeById(selected[i].id);
selModel.select(node);
}
} else if (selected) {
var node = tree.getNodeById(selected.id);
selModel.select(node);
}
}
}
})
I think the issue is something to do with the root node not being created at this stage? However a way to fix escapes me (beyond my skills). Any ideas?

Thanks
MrSparks

Condor
15 Sep 2010, 3:37 AM
Maybe some extra checks:

createNode: function(attrs) {
if (attrs && attrs.id && expanded && expanded[attrs.id]) {
attrs.expanded = true;
}
this.constructor.prototype.createNode.call(this, attrs);
},

MrSparks
15 Sep 2010, 4:09 AM
Maybe some extra checks:

createNode: function(attrs) {
if (attrs && attrs.id && expanded && expanded[attrs.id]) {
attrs.expanded = true;
}
this.constructor.prototype.createNode.call(this, attrs);
},

Getting the same error with the new config.

Condor
15 Sep 2010, 4:13 AM
The error you metion is from the setRootNode method. I'm not calling setRootNode from my code; are you?

MrSparks
15 Sep 2010, 4:19 AM
The error you metion is from the setRootNode method. I'm not calling setRootNode from my code; are you?

Just double checked and I'm not calling setRootNode anywhere in the code. Here is a profile from IE, which does refer to setRootNode. very odd!?

TreeLoader 1 0.00 0.00
addListener 5 0.00 0.00
JScript - window script block 4 0.00 0.00
Component 1 0.00 0.00
getId 1 0.00 0.00
register 1 0.00 0.00
getKey 1 0.00 0.00
initComponent 1 0.00 0.00
initComponent 1 0.00 0.00
initComponent 1 0.00 0.00
initComponent 1 0.00 0.00
initComponent 1 0.00 0.00
enableBubble 1 0.00 0.00
TreeEventModel 1 0.00 0.00
setRootNode 1 0.00 0.00
destroyRoot 1 0.00 0.00
createNode 1 0.00 0.00
createNode 1 0.00 0.00
AsyncTreeNode 1 0.00 0.00
TreeNode 1 0.00 0.00
Node 1 0.00 0.00
TreeNodeUI 1 0.00 0.00
TypeError 1 0.00 0.00

Condor
15 Sep 2010, 4:25 AM
Oops... forgot something very essential:

createNode: function(attrs) {
if (attrs.id && expanded && expanded[attrs.id]) {
attrs.expanded = true;
}
return this.constructor.prototype.createNode.call(this, attrs);
},

MrSparks
15 Sep 2010, 4:32 AM
Oops... forgot something very essential:

createNode: function(attrs) {
if (attrs.id && expanded && expanded[attrs.id]) {
attrs.expanded = true;
}
return this.constructor.prototype.createNode.call(this, attrs);
},

I'd tried that at a guess (based on a forum post I found) but when its added the TreePanel does not retain it's state after a tree.getRootNode().reload();

It looks like its retained the original state (when it was originaly created) and just keeps reloading that original rather that the last state....

I just assumed it was not working becuase of the error.

Should I be calling something else to reload from my keyup event listener?


Update: in bold, hope that makes more sense now. :)

MrSparks
24 Sep 2010, 4:49 AM
@Condor

I've tried a various flavours of trying to get this up and running but so far no success. The Tree reloads but always back to it's default values. i.e. the state changes are not persistent after a reload.

I've been working with a stripped down config for simplicity (below). And... for reload I'm calling mytree.getRootNode().reload();

Any idea why the state changes don't persist?



// Configure loader to expand and select previously selected/expanded nodes
var selected, expanded;
var loader = new Ext.tree.TreeLoader({
dataUrl: 'mytreedata.cfm',
preloadChildren: true,
createNode: function(attrs) {
if (attrs.id && expanded && expanded[attrs.id]) {
attrs.expanded = true;
}
return this.constructor.prototype.createNode.call(this, attrs);
},
listeners: {
load: function(loader, node) {
var mytree = node.getOwnerTree();
var selModel = mytree.getSelectionModel();
if (Ext.isArray(selected)) {
for (var i = 0; i < selected.length; i++) {
var node = mytree.getNodeById(selected[i].id);
selModel.select(node);
}
} else if (selected) {
var node = mytree.getNodeById(selected.id);
selModel.select(node);
}
}
}
});

// Create the TreePanel
var mytree = new Ext.tree.TreePanel({
loader : loader,
preloadChildren: true,
autoScroll: true,
requestMethod: 'GET',
root: {},

});

// Gather selected and expanded states
var selModel = mytree.getSelectionModel();
selected = selModel.getSelectedNodes ? selModel.getSelectedNodes() : selModel.getSelectedNode();
expanded = {};
mytree.getRootNode().cascade(function(n){
if (n.expanded) {
expanded[n.id] = true;
}
});
Static JSON DATA for testing (from mytreedata.cfm)


[{
id: 1,
text: 'Node 1',
expanded: true,
children: [{
text: 'B child Node',
id: 2,
leaf: true
}]
},
{
id: 3,
text: 'Node 2',
expanded: true,
children: [{
text: 'B child Node',
id: 4,
leaf: true
}]
}]

MrSparks
24 Sep 2010, 12:30 PM
@Condor
I've just dropped a copy of this question into Premium Help. (not sure how to move a thread)