1

I have an array of data in $key => $value pairs that I wanted to display nicely to the user. As I was trying to think of ways to do it, I came up with the though of:

It'd be nice if I could just pass the JSON to the page and have a javascript tree made.

Then I found jsTree, which seemed to fit my requirements perfectly. After reading the documentation, I found the JSON format which was needed to to be passed to create the tree - so I created a recursive function to transform it in to the correct array format, and then json_encode'd it and passed it to the constructor. The problem was, json_encode didn't create the children nodes properly, so it was completely unusable. I like general solutions, without having to format the data from the source for one particular type of display (being jsTree in this case), and decided I'd want to be able to take any array and display it with jsTree efficiently. After hours of searching I was unable to find a drop-in solution to this problem.

So, my question is, what is the best way to convert a PHP array to something that jsTree will play nicely with. Added bonus if the children nodes don't have icons, nor the space where the icon was, as I am personally not dealing with a file system and have no need for an icon where there are no children nodes.

Jon
  • 4,746
  • 2
  • 24
  • 37

1 Answers1

2

Creating jsTree from Array

First, let's tackle how to turn an array in to something jsTree will play nicely with, since json_encode doesn't work properly, we'll result to an unordered list format. Since the input array can contain either scalar data or an array, it will need to be recursive.

For this, we'll create the array2jstree function, which essentially turns the array in to an unordered list that is not specific to jsTree with one class exception.

function array2jstree($ar){
    $out = '';
    foreach($ar as $k => $v){
        $out .= "<li>$k";
        if(is_array($v)){
            $out .= array2jstree($v);
        }else{
            $out .= "<ul><li class=\"jstree-nochildren\">$v</li></ul>";
        }
        $out .= '</li>';
    }
    return "<ul>$out</ul>";
}

What this does is goes through each element in the array and, if another array, calls itself and creates an unordered list underneath the 'parent' <li> element, if not an array, still expands to a new list, but it only contains the value. In this way, an array of:

array(
    'data' => 'value'
)

Will be expanded upon data showing value as it's child.

Note the class for the non-array value, being jstree-nochildren. This class is not part of jsTree, but is being used for any item that has no children (so the icon can be removed successfully.)

Now, all that is needed is to drop the function in, and pass an array to it for a nice working jsTree, with icons. Putting it together to show how to use it would be (using echo as an example, but can easily be pass as a variable to a templating engine, etc:

echo '<div id="cTree">'. array2jstree(array('name' => $myArray)) .'</div>';

The reason to pass a new array to the function is so that it has a defined 'root' node to expand, omit it if you don't need a root node.

And the JS to initialize it as a jsTree:

    <script>
    $('#cTree').jstree();
    </script>

Now you have a drop-in function to convert arrays to a jsTree! Now, back to the issue of no icon for nodes that have no children, we will create a style based on that class we assigned earlier jstree-nochildren, and working with what jsTree converts the list to, the only style you need to add is:

.jstree-nochildren > a > .jstree-icon { display:none !important; } 

Now you are all done!

Jon
  • 4,746
  • 2
  • 24
  • 37