I have a Tree Panel which I expand programmatically.
When I expand a node, I would like to "jump to" this node, I mean to scroll to it.
How to scroll a tree panel to a specific node ?
UPDATE:
I use Ext 4.1
Try using selectPath() http://docs.sencha.com/ext-js/4-0/#!/api/Ext.tree.Panel-method-selectPath
In extjs 3.x you can try calling focus() on the TreeNodeUI (myNode.ui.focus())
The tree is asynchronously loading every node, and you need to call to focus only after all the nodes have been loaded. What you are going to need to do is to set autoLoad to false on your root node, then later in the code manually load the root node for the first time using:
rootNode.expand(true, function(){
myTreePanel.getView().focusRow(nodeyouwanttofocus);
});
doing it this way allows you to use the first parameter of the expand function that makes the expand fully recursive and also assures that the second parameter that is a function only executes after all the nodes are loaded, guarenteeing that the view is the correct height and that the node exists visually.
Another option that allows more flexability is to hook into the expand event:
var myTreeStore = Ext.create("Ext.data.TreeStore", {
listeners: {
expand: function(theParentNode){
theParentNode.eachChild(function(node){
if(nodeIWantSelected == node)
myTreePanel.getView().focusRow(node);
}
}
}
});
and you can use the .select of the selection model to hook in to select the node (and I think it may focus the node too).
I haven't tried 'selectPath' as suggested by Sha before, which seems a lot easier to use, but you can hook in the focusRow function as the callback and I think that would work too.
You can use tree.getView().focusRow(), like it:
tree.expandPath(
'/root/1/2/3',
'id',
'/',
function() {
tree.getView().focusRow(tree.getStore().getNodeById('3'));
}
});
But, if your tree use animate: true and load every node asynchronously and any node in the path not loaded yet this approach doesnt work (tree is not scrolled to the selected node because of multiple layout updates).
As workaround you can:
set animate: false for tree;
add 'afterlayout' listener, like this:
tree.on('afterlayout', function() {
tree.getView().focusRow(tree.getSelectionModel().getSelection()[0]);
}
I guess you can add this handler when needed and remove it when everything is done.
Related
I'm building a tree which will be loading its data on demand, so, it will be loading the first level of data, then if I click the + it should load that node children, if node is not leaf.
I've tried with itemclick, itemdblclick, select, but none of these events is fired when click the +.
Maybe a naive question, how can I capture the click on the + or -?
You can get those events using the itemexpand and itemcollapse listeners
listeners: {
itemexpand: function(nodeinterface,eOpts){
console.log('item expanded');
},
itemcollapse:function(nodeinterface,eOpts){
console.log('item collapsed');
}
},
I found a solution myself, and here is what I did:
in the view:
I needed to add: displayField: 'text' in the treepanel config and then point all the data to be displayed to that config.
I am working with ExtJS 4.2 and have two tree panels. I am also using treeviewdragdrop to be able to drag some nodes from left tree to right.
Now let me explain the problem I am having.
You can see that AMAZONE is the Service Alias and as soon you change something in that textfield, there is a listener on blur to update right tree's root text. Since its AMAZON now, the root is also AMAZON. Then you can drag items from left to right like i have in the picture (Yhoo, dbTask).
This is when I get into trouble. When I go back and change the SERVICE ALIAS, it changes the name but nodes disappear since I have to reload the root node again in order to see the updated root text. Is there a way to maybe update the view, that actually updates whatever changed were made. This what I have now.
This is the code
listners:
{
blur: function()
{
var root_node = right_tree.getRootNode();
root_node.data.text = new_alias_name;
right_tree.store.load(); // or reload()
}
}
I know I can save dropped node into a variable and as soon as I reload the tree, I can assign those as children. But something tells me there should be simpler way. Thnaks ;)
Use:
root_node.set('text', new_alias_name');
And remove the call to load.
I have a treepanel inside my form. The code is
{
xtype:'treepanel',
rootVisible:false,
hidden:true,
autoload:false,
store:{autoload:false,proxy:{type:'ajax',url:'../json/objectList.php?id='+id},root:{text:'Objects',id:'src',expanded:true}},
listeners:{
show:function(){
this.store.load();
}
}
}
The problem is, I want to prevent loading before the tree is shown. But setting autoload to false does not have any effect. I still see a server request, even if the tree is hidden.
The autoLoad property does not work for tree stores as the load is based on the expansion of the node as you are doing for root. This is what I do to overcome it.
In your store confing
root:{
text:'Objects',
id:'src',
expanded:true,
children:[]
}
Setting an empty children object will prevent the store load. Then all you need to do is set up a listener on the tree view to load the store as you have done. You will need to modify the server code to return the data without the children property...so just the array.
I have a treegrid and I want to update just one node with its childs. So I have tried like this:
store.load({
node: store.getNodeById(1)
});
That updates childs, but not the node itself. So how can I update node and childs? It would be best if it would require just one request to the database.
There isnĀ“t any way to do it by configuration, it just works as design. What you can do is a little trick after load the node's children in order to manipulate the tree nodes to update the node itself manually.
See the images. They show the behaviour you expect.
This is working okay in jsfiddle: http://jsfiddle.net/lontivero/jBTWn/3/
Basically, the idea is, as I just said, manipulate the tree after load the children. In my example this is done by:
var node = store.getNodeById(1);
store.load({
node: node,
callback: function(newRecord) {
var parent = node.parentNode;
parent.insertBefore(newRecord[0], node);
parent.removeChild(node);
},
params: {
json: Ext.JSON.encode(updated_data)
}
});
Good luck!
I need to prevent tree node anchor from navigating current page, but the anchors have to keep showing its link (no hash).
I tried to put return false when it sets up the listener:
...
listeners : {
click : function (node) {
/* some processes */
return false;
}
}
...
Seems it is useless, the anchors are still firing its href.
I can't do onClick injection for all nodes, because the nodes are loaded on demand.
Any idea's?
I can't do onClick injection for all
nodes, because the nodes are loaded on
demand.
Not necessarily, have you thought about doing this with a different approach, i.e.:
YOURTREEPANELCOMPONENT.on('click',function(currentnode, clickevent){
// prevent href from being called and the page from loading
clickevent.stopEvent();
// what else to do when the node is clicked
});