Search code examples
inserttreeviewtabulator

Tabulator - Adding TREE items at any hierachical level


Not having found any way to do that in the Tabulator documentation/examples, I have searched for a while how to do this very basic thing.

I have seen this answer but it relies on JQuery that I don't know and I cannot use in my limited environment (plus, it does not seem to be resolving the misplaced TREE branches and [+]/[-] TREE buttons).

Below is my (malfunctioning) pure-JS code that I would like to see performing correctly: it just prunes a "NEW" item when you click an existing TREE item (but the TREE attachments, indentation and [+]/[-] buttons go nuts).

As far as I can tell, the result displayed by alert() is correct. Could that be a Tabulator library bug?

<!DOCTYPE html>
<html lang="en">
<head><title>Tree</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">

<link href="https://unpkg.com/[email protected]/dist/css/tabulator.min.css" rel="stylesheet">
<script type="text/javascript" src="https://unpkg.com/[email protected]/dist/js/tabulator.min.js"></script>

<style>
body{margin:1.5%}
#treediv{width:300px;height:250px;font-size:1.6em;background:#777};
</style>

<script type="text/javascript">
function $def(variable) {return(typeof variable !== 'undefined')}

var count = 0; // item #
window.onload=function()
{
   var treedata = 
   [ {name:"Bob"}, {name:"Tom"}, 
     {name:"Jane", _children:[{name:"Eric"}]}, 
     {name:"John", _children:[{name:"Lin", _children:[{name:"Eva"}]}]} 
   ];

   var tree = new Tabulator("#tree", 
   {  height:"250px", layout:"fitColumns", headerVisible:false,
      data:treedata, dataTree:true, dataTreeChildIndent:25,
      dataTreeStartExpanded:true, selectable:1,
      columns: [ {field:'name'} ],
      rowClick:function(e, row)
      {
        var children = row.getData()["_children"];
        var nbr = $def(children) ? children.length : 0;
        count++;

        row.select();     
        var selectedRows = tree.getSelectedRows();
        var root = selectedRows[0].getTreeParent();
        if(root) 
        { var r = root; parents = 1;
          while(r){r = r.getTreeParent(); if(r){root = r}}
        } else root = selectedRows[0];

        if(!nbr) // easy case, define _children[]
        {
           row.update({_children:[{name:"pNEW" + count}]});
           alert(JSON.stringify(root.getData()));
        }
        else // _children[] already exists, add NEW ITEM
        {
           children.push({name:"cNEW" + count});
           row.update({_children:children});
           alert(JSON.stringify(root.getData()));
        }
      },
   });
}
</script>
</head><body>
   <div id="treediv"> <div id="tree"></div> </div>
</body></html>

Solution

  • Since the JSON array is correctly updated - but badly rendered, the (uggly) workaround is just to add the following line of code at the end of rowClick:function(e, row){}:

    rowClick:function(e, row){
      ...    
      tree.setData(tree.getData()); // make tree use new JSON array
    }
    

    Someone has then suggested a (potentially) better API call:

    rowClick:function(e, row){
      ...    
      tree.redraw(true); // make tree use new JSON array
    }
    

    Yet, it does not resolve the problem at all: tree.redraw() is buggy and might be the source of the problem in the first place.

    With my workaround, the Tabulator library is correctly rendering the TREE (proof that our point-and-click code was working and that this is a Tabulator bug).

    This can safely be used as a FUTURE-SAFE WORKAROUND (that is, if your TREE is not too large and slowing-down the forced refresh...) until the Tabulator library is fixed.