can anyone give a 5-liner (or thereabouts) how-to on Grid drop 'n' drag?
January 7th, 2009I know that the previous incarnation of Grid DnD required some external (i.e. outside of the Grid classes) wiring that was only detailed in a blog post; it seems like everything is more integrated in Beta. I realize it's early, just eager to get going.
Thanks in advance,
Rogers
I had to add ddGroup : 'TreeDD'
new Ext.tree.TreePanel({
....
dropConfig: {
completeDrop : function(e){
e.target.ui.endDrop();
e.target.ui.highlight(); // remove this if you don't want it
this.tree.fireEvent("nodedrop", e);
}
}
...
Note: your beforenodedrop handler will need to return something for e.dropNode, but it can be an empty object, e.g. {}. (See beforenodedrop above setting e.dropNode).
What's currently possible:
1) Make all nodes folders. This makes logical sense, but then empty folders still have a "+" next to them as if they can be expanded when they actually can't. It also makes it impossible to know at a glance which nodes actually have children.
2) Make empty nodes appear as leafs. This solves the visual issues with (1), but has a secondary effect on things like DnD which assume that leafs can't be dropped on and so treat them differently (no highlight).
3) Use CSS to set a :hover for all tree nodes (the solution I'm currently using). This causes a bit of UI confusion as now it appears you are going to drop on a node when maybe you are dropping *between* nodes.
Frankly I'm not sure what the *right* solution is... maybe a third (besides leaf and folder) type for nodes (i.e. empty_folder) or an additional flag (folder_empty) that allows a node to be a folder but informs Ext that it currently contains nothing and so can't be expanded?
There's already a solution for this that has been discussed a lot in these forums. I just posted it yesterday too. Basically, you can have a node that doesn't have any children and knows it doesn't have children by telling it via the node attributes:
children:, // no children
expanded:true // make it read the children and find out it has none
Try adding a listener for beforenodedrop on the tree. See more information on this thread: http://extjs.com/forum/showthread.php?p=144728
I am trying to drag items from a grid onto a tree; however, I don't want the items to actually be added to the tree. I'm working on a UI that is similar to an email client, where the data from the grid rows should be moved/copied to the location indicated by the target node, but won't actually become part of the tree.
So ... I am able to wire up the grid and tree for drag-and-drop, but am not sure how best to achieve the effect of a "nodedrop" event when the dropped nodes are not proper "nodes", but rather are grid rows.
I notice that the "nodedrop" event is not being fired at all, when the items being dropped are not TreeNode objects (or some sort of "node", I haven't looked into it fully). I assume this is why, in the example above, new TreeNode objects were being created in the "beforenodedrop" event.
If I don't want to create new TreeNode objects, would the appropriate place to copy/move items, updating the grid (and possibly updating the tree, but no new TreeNode objects), be in a "beforenodedrop" event handler?
Is there something simpler I'm just missing here? (likely)
Thanks in advance for any help!
Hans
Seems the easiest thing is to do your work in the 'beforenodedrop' handler then simply set e.cancel = true before returning.
What's currently possible:
1) Make all nodes folders. This makes logical sense, but then empty folders still have a "+" next to them as if they can be expanded when they actually can't. It also makes it impossible to know at a glance which nodes actually have children.
2) Make empty nodes appear as leafs. This solves the visual issues with (1), but has a secondary effect on things like DnD which assume that leafs can't be dropped on and so treat them differently (no highlight).
3) Use CSS to set a :hover for all tree nodes (the solution I'm currently using). This causes a bit of UI confusion as now it appears you are going to drop on a node when maybe you are dropping *between* nodes.
Frankly I'm not sure what the *right* solution is... maybe a third (besides leaf and folder) type for nodes (i.e. empty_folder) or an additional flag (folder_empty) that allows a node to be a folder but informs Ext that it currently contains nothing and so can't be expanded?
I'm worried that my implementation may break in a future release.
Here's the code for the notifyDrop that I finally settled on:
notifyDrop: function(source, e, data) {
var msgids='';
for(x=0;x
//Remove from current store:
r.store.remove(r);
msgids+=r.Uid+',';
}
//The target Node was in dragDropData in the event object:
console.log(e.dragDropData.target.id) //shows the id of the node dropped on.
}
Then, I just pretty much removed all the other event listeners.
-- W.G.
new Ext.tree.TreePanel({
id:'fldMailboxes',
animate:true,
enableDrop:true,
title:'Mailbox',
rootVisible:true,
loader: new Ext.tree.AjaxProTreeLoader({
//AjaxPro adapter for TreeLoader
ajaxProCall: function(id, callback){
return SWIRLMAIL.AJAX.GetFolders(true, callback)
}
}),
lines: true,
ddGroup: 'FoldersDropGroup',
selModel: new Ext.tree.DefaultSelectionModel(),
listeners: {
click: function(node, evt) {
currFolder=node.id;
store.load({params:{folder:currFolder}});
//msgViewer.body.update('');
},
nodedrop: function(tree,target,data,point,source,e,node){
console.log('dropped in listeners');
}
},
completeDrop: function(e){
console.log('complete');
e.target.ui.endDrop();
this.tree.fireEvent("nodedrop",e);
},
beforeNodeDrop: function(e){
console.log('before');
},
nodedrop: function(node,source,e,data){
console.log('dropped');
},
dropConfig: {
ddGroup: 'FoldersDropGroup',
dropAllowed: true,
appendOnly: true,
completeDrop: function(e){
console.log('complete');
e.target.ui.endDrop();
this.tree.fireEvent("nodedrop",e);
},
beforeNodeDrop: function(e){
console.log('before');
},
nodeEnter:function(node,source,e,data){console.log ('nodeEnter');},
notifyDrop: function(source, e, data) {
console.log(data);
console.log(source);
console.log(e);
//console.log(this);
var msgids='';
for(x=0;x
//console.log(r.data.Uid);
//TODO: Tell Ajax to move these.
//Remove from current store:
r.store.remove(r);
msgids+=r.Uid+',';
}
//SWIRLMAIL.AJAX.MoveMessages(currFolder,
e.dropNode=true;
e.cancel=false;
e.point=false;
return true;
},
nodeDrop: function(node,source,e,data){
console.log('dropped');
}
},
containerScroll: false,
root: new Ext.tree.AsyncTreeNode({
text: 'Folders',
draggable: false,
expanded: true,
id: 'mailbox-folders'
})
})
As you can probably tell, I've experimented quite a bit with several different event listeners... :)
-- W.G.
tree2 = new Tree.TreePanel('tree2', {
ddGroup : 'TreeDD',
enableDrop:true,
dropConfig: {
completeDrop : function(e){
alert('in'); //this is not getting display, so doubt if it is even coming inside!
e.target.ui.endDrop();
e.target.ui.highlight(); // remove this if you don't want it
tree2.fireEvent('nodedrop', e);
},
animate:true,
containerScroll: true
}
});
// declaring a node that is going to be the tree's root
var root2 = new Tree.TreeNode({
id: "root2",
text: "Main Menu",
draggable:false,
leaf: false,
allowDelete: false,
allowDrop: true//,
//children: ,
//expanded: true
});
tree2.setRootNode(root2);
tree2.render();
tree2.expandAll();
tree2.on('nodedrop', function(e){
alert('in nodedrop'); //never display this!!!
});
tree2.on('beforenodedrop', function(e){
alert('in before node drop:' + e.target.id); //This alert msg is getting displayed
});
Following is a code for grid creation:
// create the Grid
var grid = new Ext.grid.Grid('grid-example', {
ddGroup : 'TreeDD',
enableDrag: true,
id: 'grid1',
ds: ds, //ds is MemoryProxy and reader for this is ArrayReader
cm: colModel
});
var layout = Ext.BorderLayout.create({
center: {
margins:{left:3,top:3,right:3,bottom:3},
panels: [new Ext.GridPanel(grid)]
}
}, 'grid-panel');
grid.render();
Can anyone please point me out the what I'm doing wrong? Why 'nodedrop' event is not getting fired:((. Appreciate any kind of help/pointer.
Thanks.
I've set the ddGroup on the Ext.tree, but do I have to set it somewhere in the grid?
Your TreePanel would actually handle the drop (and drag over). The grid is a standard DragZone/DragSource so it implements "notify" drag and drop functionality. So any time a DragSource is dragged over a Tree (DropTarget), it notifies the target it is over it and allows the the target to handle the drag over/drop (this is the reverse of standard YUI DD).
All drag drop interaction passes "data'. That data contains information about what is being dragged over the target. In this case, the source is a grid and it provides an object with the following properties:
grid: the grid
rowIndex: the row index the actual mouse down happened on
selections: an array of records - the selections in the grid when the drag started
beforenodedrop can be used to supply TreeNodes if the DragSource doesn't support getTreeNode. beforenodedrop passes 1 event object, with lots of properties, 1 of which is "data". That would be our data from the grid.
So, an example tree's beforenodedrop (from XTrack):
// watchList is a TreeNode
tree.on('beforenodedrop', function(e){
var s = e.data.selections, r = ;
for(var i = 0, len = s.length; i < len; i++){
var ticket = s[i].data.ticket; // s[i] is a Record from the grid
if(!watchList.findChild('ticket', ticket)){ // <-- filter duplicates
r.push(new xt.TreeNode({ // build array of TreeNodes to add
allowDrop:false,
text: 'Ticket #' + ticket,
ticket: ticket,
action: 'view',
qtip: String.format('{0}
{1}', s[i].data.summary, s[i].data.excerpt)
}));
}
}
e.dropNode = r; // return the new nodes to the Tree DD
e.cancel = r.length < 1; // cancel if all nodes were duplicates
});
Then on the actual drop:
tree.on('nodedrop', function(e){
watchList.setText(String.format('My Watch List ({0})', watchList.childNodes.length));
storeWatchList();
});
Hopefully this at least helps.
PS.
The "notify" functionality was on my blog at some point, I believe the TreePanel preview post.
For 1.1 we are planning on a completely new grid drop implementation - as advanced as the TreePanel's drag drop. However there is no way we could get this in and fully tested by the 1.0 release date.
#If you have any other info about this subject , Please add it free.# |