can anyone give a 5-liner (or thereabouts) how-to on Grid drop 'n' drag?

January 7th, 2009
  • I see from the sticky that Grid DnD is back (and I can drag selected rows on the examples, although the ordering doesn't seem to change), but it's not immediately obvious from the source how it's used. There seem to be two parameters, enableDrag and enableDragDrop (or names close to that), that trigger whatever wiring needs to take place ... could someone please post a quickie explanation for creating a couple of grids and wiring one to accept dragged rows from the other? Is this possible in the current build?

    I 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


  • Got it..

    I had to add ddGroup : 'TreeDD'


  • Try adding this to the config for your tree (untested and could break everything, but should work):

    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).


  • Looks like bag ... (may be) Im using treepanel also for grouping grid data. All was working fine until i have puted TreePanel to Layout which have made TreePanel horisontally scrolled . From this time DND works rather strange - sometimes work and sometimes not - user should to move mouse in TreePanel area to make DND action active . But when i resize panel to size when scrolling dissapeares - all became good again :) .


  • One thing I have a problem with is that leaf nodes don't highlight when you drag over them. I take it this because Ext assumes that leaf nodes can't have children. This makes sense, but there's some UI awkwardness here no matter how you choose to do it.

    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


  • I’m trying to achieve drag and drop between grid and tree widgets. I’ve followed all the guidelines (I think so) mentioned in this thread. Problem is for some reason ‘nodedrop’ event on tree is not getting called.

    Try adding a listener for beforenodedrop on the tree. See more information on this thread: http://extjs.com/forum/showthread.php?p=144728


  • I have a follow-on question to the correct approach to drag items from a grid onto a tree.

    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


  • I'm doing exactly the same thing (grid to tree, but without actually wanting to append nodes).

    Seems the easiest thing is to do your work in the 'beforenodedrop' handler then simply set e.cancel = true before returning.


  • One thing I have a problem with is that leaf nodes don't highlight when you drag over them. I take it this because Ext assumes that leaf nodes can't have children. This makes sense, but there's some UI awkwardness here no matter how you choose to do it.

    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 finally found that in the notifyDrop, the "event" object has an object called "dragDropData". This in turn includes the target (which is the node the drop was made onto). So, in general, I did finally get the effect that I wanted, but I still don't understand why none of the other events seem to fire for me when dragging GridPanel rows onto the TreePanel....

    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 var r=data.selections[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.


  • I am also trying to find out.. but it seem that you can only drag and drop rows from one grid to another and not to the same grid...like we used to do.


  • I've tried every which way but loose to get the dropNode event to fire when dragging grid rows from a GridPanel to a TreePanel. For some reason, the ONLY (and I mean ONLY) event to fire in the TreePanel is "notifyDrop". I'm done experimenting... anyone have a good solution. I've read about 8 different forum articles here with 8 different 'solutions', but none seem to work for me. I really must know the node that is being dropped on. I'm not trying to add any new nodes, just trying to capture the fact that the user has dragged some rows over to the treeNode and dropped it. Then I want to do some processing based on that fact.


    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 var r=data.selections[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.


  • I’m trying to achieve drag and drop between grid and tree widgets. I’ve followed all the guidelines (I think so) mentioned in this thread. Problem is for some reason ‘nodedrop’ event on tree is not getting called. Following is a code for tree:

    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.


  • What about dragging row(s) from a grid to a tree node? Any pointers on where to start?


  • I can't get these events (beforenodedrop, and nodedrop) to fire.

    I've set the ddGroup on the Ext.tree, but do I have to set it somewhere in the grid?


  • Hi Jack,

    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.


  • Integrated Grid drag is implemented. Integrated grid drop is not. It never really was in .33 either. Drop was implemented by just using a DropTarget or DDTarget pointing at a container of the grid.

    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.#
    Your name:
    E-mail:
    Telphone:

    Your comments:


    If you have any other info about can anyone give a 5-liner (or thereabouts) how-to on Grid drop 'n' drag? , Please add it free.