Open sourcing our VueJs tree structure
At Scalia, our goal is to define a new protocol to connect retailers product catalogues.
For now, the brands owners and the distributors interact through multiple product data streams from all sort. As a result, they all lose a lot of resources collecting, enriching and standardizing their partners data.
On key aspect of organizing a product catalogue is being able to categorize it. This is a basic feature in order to help them visualize that structure their data properly.
On our first trial in early 2017, we’ve started using bootstrap-treeview. It was an obvious choice as it was easy to implement and to adapt. But we quickly realized the limits of such solution.
- First, due to the lack of dynamic rendering, changes were too slow, making the whole page laggy.
- Secondly, there wasn’t enough options. For instance, we needed to display the number of children element of a node, some events like ‘Expand’ or being able to rename the node when clicking on the name.
Hence, we’ve started looking for a new tree structure. We choosed VueJs for our new tree because it’s easy to integrate to Rails 5.1+ through the webpacker gem. But most importantly, it had an exponential growth in term of users: npm show more than 1M download for the last month. Still today, the amount of contributors to VueJS continues to increase at an impressive rate.
After selecting our framework, we searched for existing tree structure projects. We found some here and there — mostly as a component within a full scale library such as iview. Unfortunately, we knew by then that this would be a key piece of our platform and that these weren’t mature enough yet. We would just bump into the exact same problems that we had with bootstrap-treeview. The last option remaining was to build our own.
The JSON data structure
Our tree takes two params: a nodes hash and customization options.
Each nodes contain its own data, like its name, the selected and expanded states, the number of children, etc. It also has a key ‘nodes’ which contain the node direct children’s who will contain the same keys and so on and so forth. The main advantage of these node imbrications is that it makes it easier to create, read and display these data.
As customization was the big missing piece of the our previous experiments we’ve decided to invest a lot of efforts into it. Pretty much anything could be chance on our tree display — from the tree and row CSS all the way to the folder icons and color scheme. One simply has to specify some options.
How it works
We’ve split things into two components: one for the overall tree and one for the rows.
When an event is triggered in a row, another event is sent to every parent components until it reaches the main tree component. This is how the tree keep all infos about the selected, checked and opened nodes.
As for the events themselves, they all can be individually enabled and/or override. Moreover, for each tree events, a custom function can be called after the event. This way we can keep the generic behavior and customize it at the same time.
Because of the customizable nodes data, we had to create a function to retrieve it. We’ve called it getNodesData and it takes 3 params:
- The first one defines the keys wanted (like the id), it can be a string (e.g. ‘id’) or an array (e.g. [‘id’, ‘name’, ..])
- The second param is a hash defining the condition, and returning the keys of the nodes who fulfill it. For example, if one only wants the checked nodes, one will send { checked: true }, or nothing if we don’t want any conditions.
- The third param define the format, either you want an array of nodes hash or an ordered tree hash.
Conclusion
We are very much happy with our tech stack choice so far. If you want a front language who can really shine when you render dynamic things, have a try at VueJs.
As far as the tree structure is concerned, we are pleased with what we’ve achieved so far. But we also realized we have a long way ahead of us and that many more options could be develop to enhance this project. Therefore, should you want to collaborate and have a stamp at it, be my guest !!
Our GitHub repo is here. Should you have any questions, don’t hesitate to chat with me directly.