Drag and drop between two panels along with the parent folder.

  1. #1

    Drag and drop between two panels along with the parent folder.

    Hello,

    There is a requirement wherein I need to drag and drop a leaf from one tree panel to another tree panel in such a way that the leaf should come along with its root folder. How can we achieve this.

    Please refer the below images:

    In the below image I will dragging 'Business Roles' and dropping in the Tree panel 2.
    Click image for larger version. 

Name:	fig1.png 
Views:	95 
Size:	23.7 KB 
ID:	24396

    The below image is an edited one, As per the below image I need to bind 'Business Roles' along with the parent folder 'Administration'
    Click image for larger version. 

Name:	fig2.png 
Views:	97 
Size:	23.9 KB 
ID:	24397

    How can I achieve this.
  2. #2
    Hello,

    Overall, you can get on the drop event the node dropped. From the node you can get its parent nodes and then rebuild the parents' structures where you dropped and, effectively drop the node on the recreated node structure under the dropped folder...

    You may want to create the parent nodes structure on the specific dropped folder, or just keep the parent nodes structure starting from the 'My Files' node.

    For example:
    - create parent nodes on specific dropped folder
    1. drop Business roles unto 'My Files':
    result: My Files -> Administration -> Busines Roles
    2. drop Engineering roles INTO Administration:
    result: My Files -> Administration -> Administration -> Engineering roles

    - create parent nodes starting from 'My Files'
    1. drop Business roles unto 'My Files':
    result: My Files -> Administration -> Busines Roles
    2. drop Engineering roles INTO Administration:
    result: My Files -> Administration -> Engineering roles

    In the first case, you will just create the parent nodes' strucute from the dropped point on.

    in the second case, you have to walk back to root and create the structure + append the record there.

    These information are just generic tips on building this. If you have trouble making it work, maybe you can provide an actual and runnable test case so we can run and reproduce on our side and then give you a more exact information.

    Some references you can also use to see how the drag-drop works are these two examples:
    - TreePanel Drag-Drop to Div
    - GridPanel Drag-Drop to TreePanel

    Hope this helps!
    Fabrício Murta
    Developer & Support Expert
  3. #3
    Hi fabricio.murta,

    I tried the approach you have mentioned to some extent and ended up something like this in the below fig:

    Click image for larger version. 

Name:	fig3.png 
Views:	117 
Size:	25.2 KB 
ID:	24398

    I could create the folder but am not being able to drop the leaf inside the newly created folder. Please check the below code :

    <%@ Page Language="C#" %>
    
    <%@ Import Namespace="System.Collections.Generic" %>
    
    <%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
    
    <script runat="server">
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!X.IsAjaxRequest)
            {
                SiteMapNode siteNode = SiteMap.RootNode;
                Node node = this.CreateNodeWithOutChildren(siteNode);
                node.AllowDrag = true;
                node.Expanded = true;
                TreePanel1.Root.Add(node);
            }
        }
    
        //page tree node loader handler
        protected void LoadPages(object sender, NodeLoadEventArgs e)
        {
            if (!string.IsNullOrEmpty(e.NodeID))
            {
                SiteMapNode siteMapNode = SiteMap.Provider.FindSiteMapNodeFromKey(e.NodeID);
    
                if (siteMapNode == null)
                {
                    return;
                }
    
                SiteMapNodeCollection children = siteMapNode.ChildNodes;
    
                if (children != null && children.Count > 0)
                {
                    foreach (SiteMapNode mapNode in siteMapNode.ChildNodes)
                    {
                        e.Nodes.Add(this.CreateNodeWithOutChildren(mapNode));
                    }
                }
            }
        }
    
        //dynamic node creation
        private Node CreateNodeWithOutChildren(SiteMapNode siteMapNode)
        {
            Node treeNode;
    
            if (siteMapNode.ChildNodes != null && siteMapNode.ChildNodes.Count > 0)
            {
                treeNode = new Node();
            }
            else
            {
                treeNode = new Ext.Net.Node();
                treeNode.Leaf = true;
            }
    
            treeNode.NodeID = siteMapNode.Key;
            treeNode.Text = siteMapNode.Title;
            treeNode.Qtip = siteMapNode.Description;
    
            return treeNode;
        }
    
        [DirectMethod(ShowMask = true)]
        public void callMe(string abc)
        {
            string folderName = abc;
    
            string nodeId = "check";
            Node node = new Node()
            {
                NodeID = "xyz",
                Text = folderName,
                Expanded = false,
                EmptyChildren = true,
                Icon = Icon.Folder
            };
            //node.CustomAttributes.Add(new ConfigItem("task", folderName, ParameterMode.Value));
            //node.CustomAttributes.Add(new ConfigItem("duration", "", ParameterMode.Value));
            //node.CustomAttributes.Add(new ConfigItem("user", "", ParameterMode.Value));
    
            //TreeSelectionModel sm = TreePanel1.GetSelectionModel() as TreeSelectionModel;
            string SelectedNode = nodeId;
            //string childNode = string.Empty;
            //string parentName = folderName;
    
            //if (sm.SelectedNodes != null)
            //{
            //    SubmittedNode Subnode = sm.SelectedNodes[0];
            //    SelectedNode = Subnode.NodeID;
            //    parentName = Subnode.Text;
            //    childNode = folderName;
            //    // AddSubFolder(folderName, nodeId, SelectedNode);
            //}
            // else
            // {
            TreePanel2.GetNodeById(SelectedNode).AppendChild(node);
            // }            
    
        }
    
    </script>
    
    <!DOCTYPE html>
    
    <html>
    <head id="Head1" runat="server">
        <title>Drag and Drop betweens two TreePanels - Ext.NET Examples</title>
        <link href="/resources/css/examples.css" rel="stylesheet" />
        <style>
            .tree {
                float: left;
                margin: 20px;
                border: 1px solid #c3daf9;
            }
        </style>
     <ext:XScript ID="XScriptdd1" runat="server">
        <script type="text/javascript">
            var beforerecorddrop = function (node, data, overModel, dropPosition, dropFn) {
               // debugger;
    
                var draggeditem = data.item.innerText;
                var folderDraggedTo = overModel.data.text;
                var depth = overModel.data.depth;
                var parentFolder;
                var from = #{HdnFolderName}.getValue();
                 #{DirectMethods}.callMe(from);
                // var view = this.view,
                //  targetNode = view.getRecord(node),
                //draggedRecords = data.records,
                //dataLength = draggedRecords.length,
                //ln = draggedRecords.length,
                //i, record;
            };
    
          
    
            var beforenodedrop = function (node, data, overModel, dropPosition, dropFn) {
               // debugger;
                if (Ext.isArray(data.records)) {
                    var records = data.records,
                        rec;
    
                    data.records = [];
    
                    for (var i = 0; i < records.length; i++) {
                        rec = records[i];
    
                        data.records.push(this.store.createModel({
                            company: rec.get("text"),
                            price: rec.get("price"),
                            change: rec.get("change"),
                            pctChange: rec.get("pctChange"),
                            lastChange: rec.get("qtip")
                        }));
    
                        rec.remove(true);
                    }
    
                    return true;
                }
            };
    
            var nodeDragOver = function (targetNode, position, dragData) {
               //debugger;
                
                var rec = dragData.records[0],
                    isFirst = targetNode.isFirst(),
                    canDropFirst = rec.get('canDropOnFirst'),
                    canDropSecond = rec.get('canDropOnSecond');
                // alert(rec.parentNode.data.text);
                #{HdnFolderName}.setValue(rec.parentNode.data.text);
                return true;//isFirst ? canDropFirst : canDropSecond;
            };
        </script>
        </ext:XScript>
    </head>
    <body>
        <form id="Form1" runat="server">
            <ext:Hidden ID="HdnFolderName" runat="server" />
            <ext:ResourceManager ID="ResourceManager1" runat="server"/>
    
            <h1>Drag and Drop betweens two TreePanels</h1>
    
            <p>The TreePanels have a TreeSorter applied in "folderSort" mode.</p>
    
            <p>Both TreePanels are in "appendOnly" drop mode since they are sorted.</p>
    
            <p>Drag along the edge of the tree to trigger auto scrolling while performing a drag and drop.</p>
    
            <p>The data for this tree is asynchronously loaded with a TreeStore.</p>
    
            <div class="tree">
                <ext:TreePanel
                    ID="TreePanel1"
                    runat="server"
                    Border="false"
                    Height="300"
                    Width="250"
                    UseArrows="true"
                    Animate="true">
                    <Store>
                        <ext:TreeStore ID="TreeStore1"
                            runat="server"
                            OnReadData="LoadPages"
                            FolderSort="true">
                            <Proxy>
                                <ext:PageProxy />
                            </Proxy>
                            <Sorters>
                                <ext:DataSorter Property="text" />
                            </Sorters>
                        </ext:TreeStore>
                    </Store>
                    <View>
                        <ext:TreeView ID="TreeView1" runat="server">
                            <Plugins>
                                <ext:TreeViewDragDrop ID="TreeViewDragDrop1" runat="server" AppendOnly="true" />
                            </Plugins>                      
                        </ext:TreeView>
    
                    </View>
    
                </ext:TreePanel>
            </div>
    
            <div class="tree">
                <ext:TreePanel
                    ID="TreePanel2"
                    runat="server"
                    Height="300"
                    Width="250"
                    Border="false"
                    UseArrows="true"
                    AutoScroll="true">
    
                    <Store>
                        <ext:TreeStore ID="TreeStore2"
                            runat="server"
                            OnReadData="LoadPages"
                            FolderSort="true">
                            <Proxy>
                                <ext:PageProxy />
                            </Proxy>
                            <Sorters>
                                <ext:DataSorter Property="text" />
                            </Sorters>
                        </ext:TreeStore>
                    </Store>
                    <View>
                        <ext:TreeView ID="TreeView2" runat="server">
                            <Plugins>
                                <ext:TreeViewDragDrop ID="TreeViewDragDrop2" runat="server" AppendOnly="true"   />
                            </Plugins>
                            <Listeners>
                                <BeforeDrop Fn="beforerecorddrop" />
                            </Listeners>
                        </ext:TreeView>
                    </View>
    
                    <Root>
                        <ext:Node Text="My Files" Icon="Folder" Expanded="true" NodeID="check" />
                    </Root>
                    <Listeners>
                        <NodeDragOver Fn="nodeDragOver" />
                    </Listeners>
                </ext:TreePanel>
            </div>
        </form>
    </body>
    </html>
  4. #4
    Hello @arjunvasisht!

    Impressive, you went quite far! Thank you very much for this perfectly runnable sample, I was able to run it here and see exactly what you meant.

    Now, just try to replace your beforerecorddrop function with this:
    var beforerecorddrop = function (node, data, overModel, dropPosition, dropFn) {
        // debugger;
    
        var draggedRecord = data.records[0].data
        var draggedNode = App.TreePanel1.store.getNodeById(draggedRecord.id);
        var srcTreeRootNode = App.TreePanel1.getRootNode();
    
        // Fill an array with the path (from leaf to root)
        var folderHierarchy = [];
        var parentNode = draggedNode.parentNode;
        while (parentNode != null && parentNode.id != srcTreeRootNode.id) {
            folderHierarchy[folderHierarchy.length] = parentNode;
            parentNode = parentNode.parentNode;
        }
                
        var curDestNode = overModel;
        if (curDestNode.isLeaf()) {
            // Dropped on a leaf that is also root?
            if (curDestNode.isRoot()) {
                return false;
            }
    
            // Move one level upper, to an actual folder node.
            curDestNode = curDestNode.parentNode;
        }
                
        // Walk from shallowest to deepest path nodes, creating them as necessary
        for (var i=folderHierarchy.length - 1; i >= 0; i--) {
            var thisNode = folderHierarchy[i];
                    
            // Check if the folder already exists
            var parentExists = false;
            for (var j in curDestNode.childNodes) {
                if (curDestNode.childNodes[j].data.text == thisNode.data.text) {
                    parentExists = true;
                    break;
                }
            }
    
            // If not, then make a copy of the node into the destination tree
            if (!parentExists) {
                curDestNode.appendChild(thisNode.copy());
            }
    
            // Get child node on dest tree
            for (var j in curDestNode.childNodes) {
                if (curDestNode.childNodes[j].data.text == thisNode.data.text) {
                    curDestNode = curDestNode.childNodes[j];
                    break;
                }
            }
        }
    
        // Drop a copy of the node in the deepest level of the structure created
        curDestNode.appendChild(draggedNode.copy());
    
        // Do not continue normal node drop operation.
        return false;
    };
    I am pretty sure it will get next to what you need.

    Notice the return false; in the end. I am pretty much replacing all the drop procedure for my own and telling drag&drop to do nothing else.

    In this example, you may notice that:
    - you can drop a same record twice: it will contain same description but different internal id.
    - on the end of the drop process, it plays the 'drop cancel' animation
    - after dropping one sub-item that haves its sub-folders created, if you drop another item from the same sub-folder, you have to drop it on the root, or else it will just doubley-create sub-folders. If this is not your intended behavior, and want to always get the same folders hierarchy, just use instead of overModel in var curDestNode, overModel.getOwnerTree().getRootNode(). You can avoid unnecessary queries (if the dropped folder is root) by:
    if (overModel.isRoot()) {
     curDestNode = overModel;
    } else {
     curDestNode = overModel.getOwnerTree().getRootNode();
    }
    So, I believe this is not exactly what you need, but a much better starting point for you to trim it down and make it work exactly as you need.

    Notice also I've didn't keep a code behind call, as this guarantees faster code execution (without client-server round trip).

    I hope this helps!
    Fabrício Murta
    Developer & Support Expert
  5. #5
    Hello fabricio.murta,

    Your code works great.!!! Thanks a ton :)

    That is exactly what i required. I have few more validations to be done. I am working on it. I may need little more help on this. So please keep this thread open for few more days.

    Thanks,
    Arjun
  6. #6
    Hello fabricio.murta,

    One problem in this approach is that when I drag and drop a folder from one tree panel to another, only folder gets created but not the data inside. Can you guide me how can I get it done.

    Click image for larger version. 

Name:	Capture.PNG 
Views:	131 
Size:	16.5 KB 
ID:	24411

    Thanks,
    Arjun
  7. #7
    On the last step in the code we provided, line 54, after creating the copy of that node, check if it is not a leaf node. If so, loop thru its child items creating a copy for each on the copied node. You'd have to recursively check if the parsed node is not a leaf, then make a copy of each its children again (and put them in the right place, checking again every added child whether they are not leaves).

    The logic is the same of the first part of the code. Think you can make it?
    Fabrício Murta
    Developer & Support Expert
  8. #8
    Thanks fabricio.murta,

    I put an if condition to check if it is a leaf and its working nicely.

    And one more thing, when I drag and drop a folder from one tree panel to another, I want the folder dragged from the source to retain in the tree panel. I mean a copy paste. But now its cut and paste.

    Is there any property which I can set to achieve a copy paste functionality.

    While drag and drop from a grid to treepanel I had just commented "rec.stores[0].remove(rec);" and I got that worked. But in tree panel I'm unable to get it done.
  9. #9
    Hello, it should be acting as a copy-paste (rather than cut-paste) if you return 'false' from the beforerecorddrop function like I shown. In the example I provided, the nodes are not removed from the original tree. (it returns false in line 58)
    Fabrício Murta
    Developer & Support Expert

Similar Threads

  1. [CLOSED] Set TreePanel Folder, Empty Folder and Leaf icons
    By RCN in forum 3.x Legacy Premium Help
    Replies: 7
    Last Post: Dec 21, 2014, 1:06 PM
  2. Replies: 0
    Last Post: Jun 12, 2014, 12:11 PM
  3. [CLOSED] drag and drop in tree panels question
    By bogc in forum 1.x Legacy Premium Help
    Replies: 1
    Last Post: Aug 31, 2011, 7:43 PM
  4. Replies: 0
    Last Post: Apr 18, 2010, 10:55 PM
  5. [CLOSED] MultiSelect with drag and drop, Drop listener
    By Jurke in forum 1.x Legacy Premium Help
    Replies: 2
    Last Post: Jan 30, 2009, 8:25 AM

Tags for this Thread

Posting Permissions