Click here to Skip to main content
15,886,873 members
Articles / DevOps

Drag and Drop between Multiple Trees in Jquery using jstree

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
21 Oct 2019CPOL10 min read 7.7K   1   2
Drag and Drop between Multiple Trees in Jquery using jstree

This was a fun project that came about because of a lack of foresight in the design process. I had argued with the Business Analyst that this project would take a substantial amount of time to complete, and that it may be easier to have a simpler control, such as 2 list controls, or one list that contains the initial groups, and one or more with the child objects, which in my case was substations and generating units. But, the B.A. pushed back and insisted on having 2 identical tree controls with multiple levels of Child objects, (of course shown by a different icon for each). I did research to find out exactly what kind of control I could simply reuse, as I thought there had to be an implementation of drag and drop between 2 tree controls! But, of course, there wasn’t. It’s trivial to implement drag and drop between 2 tree controls, but only with the exact same objects between the 2. If you wanted to have more than one ‘level’, there was no such control that existed anywhere, at least at that time (a few years ago now). Also, we were restricted to only using free controls, such as Jquery plugins, and such. Other commercial products also didn’t implement what I wanted, such as Telerik or Infragistics. So, I decided on jstree (www.jstree.com), which looked great at least. But, of course, there was no support, and not a lot of developers were using it. But, it did have events that detected drag and drop between different instances of jstree, which at least was a good starting point. By the way, the advice I got from other ‘developers’ on our team was that this little project was quite impossible, and to just give up and implement it in a trivial matter, using lists. But, I was determined so I forged ahead, and got to work with jstree.

My solution used recursion, which seemed like the easiest way to accomplish what I needed. As, if you actually think about this, before starting work on it, (sadly not a lot of developers actually think about design, and logic before coding these days), you need to implement logic to prevent drag and drop of nodes on a different ‘level’ of the current object that you are moving. And, then of course, you would have to delete all the dragged objects from the source tree, and from the database (in certain cases anyways), so it’s quite involved to implement all of this correctly, and to have it done in a few weeks which was my time that I estimated! The final solution was also much more involved than this demo, as it included more objects to ‘wrap’ around the basic solution, including ‘maps’, which would allow the user to custom make maps, with geographic locations, as a starting point for creating a destination tree ‘map’. And, other engineering terminology, which I won’t go into detail on here. A project like this is a good way to determine how a developer works. Any real developer would push back on a Business Analyst’s flawed logic, and incomplete design, especially in this case. And, at the very least, understand how it would affect your existing project, and whether it makes sense to incorporate something like this into the existing system, or not. So, something like this project would be a good way to weed out poor developers from good ones. A good developer can actually produce a great looking and functioning UI for the user. If they can’t, you should reconsider what their contribution to the project actually means. It’s very easy to just be good at one portion of the ‘stack’ such as web services, or database development, but it’s many, many times harder to actually create an entire project from scratch, and have an incredibly complex UI system working perfectly. As, if you think about it, you would realize that every level such as the database project, web services project, and of course the UI project would have to work perfectly in order to be useful to the user. So, if you are hiring a new developer, this could be the perfect project to give them in the first few weeks, as the few hours you spent interviewing them, doesn’t really determine if they are a competent developer when working on a real world problem.

Now back to the jstree solution: To get this running, the basic HTML for the placement of the controls is as follows:

Image 1

You can just place a div wherever you want a tree control to appear on your form. So for side by side controls, wrap 2 divs within another div. A basic implementation of Jstree is as follows:

Image 2

This creates the actual tree in the divGroupingsTree div. Then loads all the nodes that you want to display from the url (“/Services/CutPlaneManagement.asmx/GetAllElectricalGroupsSubstations?…) The next step is to bind whatever events you need for each tree. In my case, it’s the move_node.jstree event, which fires whenever a user moves a node to a new location either on a different tree or the same tree. This code fires when the tree detects a node that has been moved:

Image 3

This also creates a list, and ensures that all items are moved to the appropriate parent at the destination tree. The next portion of the code to examine is the call to ‘updatesubstations’ which actually updates the child nodes in the database itself. This code is taken from the ‘added groups’ tree creation code:

Image 4

The web service call basically updates the child list per map, as we are using a map id to group each ‘mapping’ of child objects:

Image 5 ….

The next part of the code recreates the hierarchy and returns the tree object to jstree:

Image 6

Jstree then uses this hierarchy to automatically recreate the parent child hierarchy as reflected by the latest actions of the user:

Image 7

Next is the JavaScript code to recursively move the nodes into the destination, and then delete any duplicate nodes / subnodes from the source tree:

Image 8

The actual function that recursively moves nodes is moveNodes(), which is rather long, and complicated:

Image 9

Image 10

This function basically tests for the amount of parent objects to move, so if it’s greater than 1, then it will eventually recursively call itself, to accomplish the moving of multiple parent/child levels below the selected node that the user actually moved. Now, the last part I wanted to show you was the createSubstationList() recursive call, which builds the list of current substations (child objects) that are in the tree after the move was completed. This list is then used by the ‘UpdateSubstations()’ server side call to actually update the list of substations in the database itself:

Image 11

This is a fairly straightforward recursive function that basically searches for any children within the parent node, and recursively traverses the HTML tree to retrieve all substations (our child object name in this case), and add to the substlist parameter.

Here is the actual demo project running. In this case, I demonstrate before and after screenshots of moving nodes from within the available ‘map’ to the destination or ‘added’ map. The first is to move a parent folder (Group) along with all child node(s) to the main root folder, and see if it will be smart enough to create all parent groups in the destination, along with the newly moved groups and ‘substation’ child nodes(s) of course! So, I will drag the ‘Edm – Edmonds’ folder from the Available to Added tree and drop it inside the ‘B.C. – British Columbia’ folder, and see what happens:

Before

Image 12

Dragged to Destination tree

Image 13

I simply clicked on the ‘Edm – Edmonds’ folder and drag it to just under the B.C. folder and drop it there. You can drop it anywhere that it makes sense, such as under the ‘GVRD – Lower Mainland’ folder as well.

Results

Image 14

Yay!, it worked! You can see that it was smart enough to create both the ‘Bby – Burnaby’ folder, then the ‘Edm – Edmonds’ folder, and place the newly moved child node in the ‘Edm – Edmonds’ folder, which is exactly what we wanted, (or at least what our engineers wanted in this case.). So, it should work in a similar fashion if you drag a child node, let's say ‘East Van 1 – East Vancouver Substation 1’ from right to left, and drop it in the B.C. root folder:

Initial State

Image 15

While Dragging from right to left

Image 16

End Result

Image 17

So, in this case, the ‘East Van – East Vancouver’ folder existed in both trees, with one unique child node in each folder. I dragged from right to left, and it successfully placed the ‘East Van 1 – East Vancouver Substation 1’ child node in the destination folder, and then deleted the source folder, as there was no reason for it to exist any longer. Of course, you can also drag whatever folder or node you want back and forth, and it should successfully create and delete parent folders accordingly, and in a way that makes sense.

In my most recent articles, I demonstrated the use of Telerik controls, and how to get them to actually work when you wanted custom functionality, versus just using them ‘out of the box’. Of course, you can see there is a trade-off for either approach. If you are using a commercial product, or other prebuilt control, which does most of what you want, usually your development time is substantially reduced, but not always! Sometimes, you need to spend quite a bit of time learning the ins and outs of the control you have decided to use. This article demonstrates an approach that is using a basic tree control, that does not have any of the functionality needed, except of course for the tree control itself. Most likely, using a commercial product, would save some time in this case, but it was an enjoyable experience, and I wanted to demonstrate what can be accomplished using this type of approach. This was also an exercise in Jquery / JavaScript, as it’s one of my first attempts at writing JavaScript and consuming a jquery plugin. This project can easily be used as a starting point for your project, that may use a graphical approach to mapping objects in your organization in the form of a tree, and includes some nice functionality to visually map out relationships for the user. In our case, it was actual geographical locations, that the user who is familiar with the region can relate to. Also, this sample was taken from an extremely complex project, that had support for multiple geographical source and destination maps. You also may be wondering why you can’t actually add nodes by right clicking the context menu. I also did create that portion of the project, but in this case, the demo is to take a pre-existing map of a Province (in our case), and to create a ‘cut’ of the map for use by engineers and technologists in the organization.

I hope you have found this project useful, and can use this in one of your future projects, or can at least appreciate the complexity of the problem, and ultimate solution. I have also included the complete source code, that you can download and re-use if you like.

Blog

DEMO HERE

This article was originally posted at https://kolaberate.com/Articles/2019/10/17/224

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
CEO Kolaberate Software inc.
Canada Canada
Chris is a .NET Architect with over 17 years of experience working with various Microsoft technologies including most recently ASP.NET, SSRS, SSIS, SSAS and Sharepoint. Chris is now C.E.O. of Kolaberate Software, based in Vancouver, B.C.

Comments and Discussions

 
PraiseCrazy! Pin
John Gelson30-Dec-19 9:26
John Gelson30-Dec-19 9:26 
GeneralMy vote of 5 Pin
John Gelson30-Dec-19 9:25
John Gelson30-Dec-19 9:25 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.