PDA

View Full Version : extjs 4 adding node to tree panel



ShrutiRuparel
2 Sep 2011, 5:19 AM
i am working with ExtJs 4 & designer 1.2. How can i get selected node of Tree Panel ? Also i want to append node to selected node & bound it to Tree store & also get effect of it in tree .
I tried following but nothing worked:

var rec = me.down('#treepanel').getSelectionModel().getSelection()[0];
var node = me.down('#treepanel').getView().getNode(rec);
var node = me.down('#treepanel').getSelectionModel().getSelectedRecords()[0];
var node = me.down('#treepanel').getView().getSelectedNodes();
var node = Ext.getCmp('treepanel').getView().getSelectionModel().getSelectedNodes();
var node = me.down('#treepanel').store.getNodeById('Todo1');

skirtle
3 Sep 2011, 2:26 PM
Not sure where you got some of those method names from, suggest you try getting them from the ExtJS 4 docs instead.

The key thing to realize is that in ExtJS 4 the node is the record.

A full example:


Ext.create('Ext.tree.Panel', {
height: 300,
renderTo: Ext.getBody(),
width: 300,
root: {
text: 'Root',
children: [
{text: 'Child 1', leaf: true},
{text: 'Child 2', leaf: true},
{text: 'Child 3', leaf: true}
]
},
tbar: [
{
text: 'Add',
handler: function() {
var tree = this.up('treepanel');
var selModel = tree.getSelectionModel();

// Could also use:
// var node = selModel.getSelection()[0];
var node = selModel.getLastSelected();

if (!node) {
return;
}

// Feels like this should happen automatically
node.set('leaf', false);

node.appendChild({
leaf: true,
text: 'New Child'
});

// The tree lines won't join up without a refresh
tree.getView().refresh();

// Not strictly required but...
node.expand();
}
}
]
});

ShrutiRuparel
3 Sep 2011, 6:12 PM
@skirtle thanx. actually i am trying to do grid to tree drag n drop. here is link : http://www.sencha.com/forum/showthread.php?145960-extjs-4-grid-to-tree-drag-drop
i (http://www.sencha.com/forum/showthread.php?145960-extjs-4-grid-to-tree-drag-drop) am able to add node to root node but i am not able to get target node in drop zone. i am trying drag n drop for first time so have not so gud idea. can u guide me as to how can i get target node in drop zone?

skirtle
3 Sep 2011, 9:04 PM
After a couple of hours of fighting with the DD code I've managed to put together a working example of grid to tree dragging. Perhaps I'm missing something obvious but it seemed that everything I tried bounced me from one complication to another, in some cases I'm pretty sure I was hitting bugs. I'm not particularly proud of the hackfest that I've produced so if anyone knows of a better way to do this please let me know.

I had two main problems. Firstly, the node kept being added with a checkbox. I found a workaround for that but then the node appeared with a + next to it that caused an explosion due to the lack of proxy. Eventually I added another workaround to force it to have an empty array of children, which prevents the proxy issue. Setting it to be a leaf didn't give me what I wanted because you can't drop nodes on a leaf.

The thought occurs it might be easier to make the source grid a tree but make it look like a normal grid. I haven't experimented with that approach yet.

Hope it's some help.


Ext.onReady(function() {
Ext.define('User', {
extend: 'Ext.data.Model',
fields: ['name', 'age']
});

Ext.create('Ext.grid.Panel', {
height: 300,
renderTo: Ext.getBody(),
width: 300,
columns: [
{dataIndex: 'name', header: 'Name', flex: 1},
{dataIndex: 'age', header: 'Age', flex: 1}
],
store: {
model: 'User',
data: [
{name: 'Tom', age: 23},
{name: 'Steve', age: 17},
{name: 'Mike', age: 48},
{name: 'Richard', age: 12}
]
},
viewConfig: {
plugins: {
dragGroup: 'user-dd',
enableDrop: false,
ptype: 'gridviewdragdrop'
}
}
});

Ext.create('Ext.tree.Panel', {
height: 300,
renderTo: Ext.getBody(),
width: 300,
columns: [
{dataIndex: 'name', flex: 1, header: 'Name', xtype: 'treecolumn'},
{dataIndex: 'age', flex: 1, header: 'Age'}
],
store: {
model: 'User',
root: {
name: 'Root',
children: [
{name: 'Roger', age: 26, children: [{name: 'Rob', age: 2, children: []}]},
{name: 'Brian', age: 98, children: []}
]
}
},
viewConfig: {
listeners: {
beforedrop: function(nodeEl, data) {
var record = data.records[0];

if (record.store !== this.getStore()) {
// Record from the grid. Take a copy ourselves
// because the built-in copying messes it up.
var copy = {children: []};

record.fields.each(function(field) {
copy[field.name] = record.get(field.name);
});

data.records = [copy];

// Remove the record from the grid
record.store.remove(record);
}

return true;
}
},
plugins: {
ddGroup: 'user-dd',
ptype: 'treeviewdragdrop'
}
}
});
});

ShrutiRuparel
3 Sep 2011, 9:56 PM
hey thnx..that partially solved my prblm..but i get error on getStore() : "Object [object Object] has no method 'getStore' "

skirtle
3 Sep 2011, 10:04 PM
Do you see that error running my code or your code? Perhaps your value of this is different to mine? It should be the grid's view. Add some logging or a breakpoint to check.

What ExtJS version are you running? My code was tested against 4.0.2 and 4.0.5.

ShrutiRuparel
3 Sep 2011, 10:32 PM
oops..i chnged it & nw its working fine from grid to tree...can u plz tell me while performing drag n drop in tree itself what if i dont want to "move" node but "copy" node from one parent to another. the default behavior moves node instead of copying it to another node :(

skirtle
3 Sep 2011, 10:39 PM
Just move the if around my copy logic to just be around the record removal:


beforedrop: function(nodeEl, data) {
var record = data.records[0];

// Record from the grid. Take a copy ourselves
// because the built-in copying messes it up.
var copy = {children: []};

record.fields.each(function(field) {
copy[field.name] = record.get(field.name);
});

data.records = [copy];

if (record.store !== this.getStore()) {
// Remove the record from the grid
record.store.remove(record);
}

return true;
}

ShrutiRuparel
3 Sep 2011, 10:56 PM
I have removed store.remove since i want to persist record in grid even after i drop it to tree.But when i do drag n drop in TREE itself, the default behaviour of TREE plugin "moves" node when i drag it from one parent node to another parent node in TREE. But i want to persist both copies of node in poth parent. So when i drag a node, there will be two copies of it. What can i do to achieve that?

skirtle
3 Sep 2011, 11:03 PM
Just get rid of the if check on the stores.

ShrutiRuparel
3 Sep 2011, 11:17 PM
i did as u said , but then it creates node with empty text :(


onBeforedrop: function(nodeEl, data,overModel) {
var record = data.records[0];


// if (record.store !== Ext.getCmp('treepanel').getView().getStore()) {
// Record from the grid. Take a copy ourselves
// because the built-in copying messes it up.


var copy = {children: []};
record.fields.each(function(field) {
copy['text'] = record.get(field.name);
});


data.records = [copy];
return true;
// Remove the record from the grid
//record.store.remove(record);
// }

}

skirtle
3 Sep 2011, 11:41 PM
onBeforedrop: function(nodeEl, data,overModel) {
var record = data.records[0];

// Take a copy ourselves because the built-in copying messes it up.
data.records = [{
children: [],
text: record.get('text') || record.get('name') // text in tree, name in grid
}];

return true;
}

ShrutiRuparel
4 Sep 2011, 12:20 AM
thanx @skirtle for all d guidance..u r saviour :)

ShrutiRuparel
5 Sep 2011, 5:23 AM
hey i just realized when i perform drag n drop in tree, the node that gets dropped to another node, does not carry its children with it i.e. i lose the children of dragged node. do u have hint what needs to b changed? i want node to get dropped alongwith its children..

skirtle
5 Sep 2011, 4:31 PM
viewConfig: {
copyDroppedRecord: function(record) {
var children = [];

if (record.store === this.getStore()) {
record.eachChild(function(child) {
children.push(this.copyDroppedRecord(child));
}, this);
}

return {
children: children,
text: record.get('text') || record.get('name') // text in tree, name in grid
};
},
listeners: {
beforedrop: function(nodeEl, data) {
// Take a copy ourselves because the built-in copying messes it up.
data.records = [this.copyDroppedRecord(data.records[0])];
}
},
plugins: {
ddGroup: 'user-dd',
ptype: 'treeviewdragdrop'
}
}

ShrutiRuparel
5 Sep 2011, 10:22 PM
thnx @skirtle its working as expected :)

ShrutiRuparel
20 Sep 2011, 12:03 AM
is there any way to save newly created node info into database?? methods like save(),insert() does not exist for TreeStore as for a JSON store :(

mxu
31 Jan 2012, 7:25 AM
hi,

I used Ext 2.2 and create a tree node first and then append it onto a node of tree panel
as an app at the link
http://www.ncbi.nlm.nih.gov/projects/SNP/GaPBrowser_prod/callGaPBrowser2.cgi?aid=1,2843&chr=1&from=189000001&to=191000001

try to migrate to Ext 4.1, and didn't find any tree node class in it, how can I create a treenode and then append to a node of tree panel ?

thanks

mxu

ShrutiRuparel
31 Jan 2012, 9:53 PM
I have dynamically set rootnode of tree as follows :


var rootnode = {
id : 2,
parent_id :1,
text : "root"
};
me.down('#myTree').getStore().setRootNode(rootnode);

And then appended child to it as follows :


me.down('#myTree').getView().addListener('beforedrop', me.onSubTreeBeforeDrop, me);
.....
onSubTreeBeforeDrop: function(node, data, overModel, dropPosition, dropFunction) {


dropFunction.wait = true;
var childid = data.records[0].data.id;
var childtext = data.records[0].data.text;
var parent = overModel.data.id;

overModel.appendChild({
id:3,
text:"child1"
});

}

Hope this helps..

nandakumaran.k
2 Feb 2012, 12:43 PM
i,

I am new to extjs. Working with extjs 4.0.2

Trying to add a new node to a node:


var vnode = tree.getSelectionModel().getSelection();
var fnode = vnode[0];
//var animationNode = fnode.appendChild(new Ext.data.NodeInterface()); // appending this way works

var animationNode = new Ext.data.NodeInterface(); // This way of node creation is not working.
animationNode.set('text', 'ANIMAT');
animationNode.set('allowDrag', false);
animationNode.set('iconCls', 'icon-menu-animation');
animationNode.set('id', 'ANIMAT');
animationNode.set('qtip', 'Animation Node');
animationNode.set('leaf', 'true');
alert(fnode.contains(animationNode)); // wanted to check if the node is already present as child
fnode.appendChild(animationNode);


Do you any idea, why creation of new node and then appending the node is not working.

healthformula
29 Mar 2012, 5:47 PM
I stumbled upon your solution but it seems like when you drag data from grid and drop into tree it gets dropped as node not as leaf. Is there anyway to drop it as leaf. Please see the attached screencast for more information
http://screencast.com/t/NolFSCHDk

luisparada
5 Sep 2013, 6:01 PM
I'm sorry but I was wondering where did you get the node.set() method, because honestly I cannot find it in NodeInterface definition inside Extjs 4.2.0 API docs, also I tried your method and it doesn't work, the difference is that you are creating a leaf node using a button, and I am creating a leaf node dragged from a grid, so the final question is, how can I convert this grid element to a valid leaf node, because all grid records dropped to the tree are by default being created as a folder or leaf:false. any thoughts ???

thank you.!!


Not sure where you got some of those method names from, suggest you try getting them from the ExtJS 4 docs instead.

The key thing to realize is that in ExtJS 4 the node is the record.

A full example:


Ext.create('Ext.tree.Panel', {
height: 300,
renderTo: Ext.getBody(),
width: 300,
root: {
text: 'Root',
children: [
{text: 'Child 1', leaf: true},
{text: 'Child 2', leaf: true},
{text: 'Child 3', leaf: true}
]
},
tbar: [
{
text: 'Add',
handler: function() {
var tree = this.up('treepanel');
var selModel = tree.getSelectionModel();

// Could also use:
// var node = selModel.getSelection()[0];
var node = selModel.getLastSelected();

if (!node) {
return;
}

// Feels like this should happen automatically
node.set('leaf', false);

node.appendChild({
leaf: true,
text: 'New Child'
});

// The tree lines won't join up without a refresh
tree.getView().refresh();

// Not strictly required but...
node.expand();
}
}
]
});