Tree Palette multiple root nodes

Hi ,

I am working on creating a palette in form of a tree. I have data in the following format.

var nodeDataArray = [
{"key":1, "name":"Stella Payne Diaz", "title":"CEO"},
{"key":2, "name":"Luke Warm", "title":"VP Marketing/Sales", "parent":1},
{"key":3, "name":"Meg Meehan Hoffa", "title":"Sales", "parent":1},
{"key":4, "name":"Peggy Flaming", "title":"VP Engineering", "parent":1},
{"key":5, "name":"Saul Wellingood", "title":"Manufacturing", "parent":3},
{"key":6, "name":"Al Ligori", "title":"Marketing", "parent":1},
{"key":7, "name":"Dot Stubadd", "title":"Sales Rep", "parent":4},
{"key":8, "name":"Les Ismore", "title":"Project Mgr", "parent":5},
{"key":9, "name":"April Lynn Parris", "title":"Events Mgr", "parent":6},
{"key":10, "name":"Xavier Breath", "title":"Engineering", "parent":4},
{"key":11, "name":"Anita Hammer", "title":"Process", "parent":5},
{"key":12, "name":"Billy Aiken", "title":"Software", "parent":1},
{"key":13, "name":"Stan Wellback", "title":"Testing", "parent":1},
{"key":14, "name":"Marge Innovera", "title":"Hardware", "parent":1},
{"key":15, "name":"Evan Elpus", "title":"Quality", "parent":5},
{"key":16, "name":"Lotta B. Essen", "title":"Sales Rep", "parent":1},
{"key":17, "name":"Lotta B. Essen", "title":"Sales Rep"},
{"key":18, "name":"Lotta B. Essen", "title":"test Rep"},
 ];

Last two nodes of the nodeDataArray do not have any parent. But my tree appears like this.
tree

I want to show them as different root nodes in tree structure(as they do not have any parent). Is it possible using the same make tree method. Or do i need to do something else.

My code goes here in codepen.

I could not get your CodePen to work. And it’s much too small to read when embedded here.

Your screenshot looks correct – those two extra “Lotta B. Essen” nodes are indeed at the root level. What do you want to be different?

I tried a different set of data which is as follows.
var nodeDataArray = [
{“key”:1, “name”:“Stella Payne Diaz”, “title”:“CEO”},
{“key”:2, “name”:“Luke Warm”, “title”:“VP Marketing/Sales”, “parent”:1},
{“key”:3, “name”:“Meg Meehan Hoffa”, “title”:“Sales”, “parent”:1},
{“key”:4, “name”:“Peggy Flaming”, “title”:“VP Engineering”, “parent”:1},
{“key”:5, “name”:“Saul Wellingood”, “title”:“Manufacturing”, “parent”:3},
{“key”:6, “name”:“Al Ligori”, “title”:“Marketing”, “parent”:1},
{“key”:7, “name”:“Dot Stubadd”, “title”:“Sales Rep”, “parent”:4},
{“key”:8, “name”:“Les Ismore”, “title”:“Project Mgr”, “parent”:5},
{“key”:9, “name”:“April Lynn Parris”, “title”:“Events Mgr”, “parent”:6},
{“key”:10, “name”:“Xavier Breath”, “title”:“Engineering”, “parent”:4},
{“key”:11, “name”:“Anita Hammer”, “title”:“Process”, “parent”:5},
{“key”:12, “name”:“Billy Aiken”, “title”:“Software”, “parent”:1},
{“key”:13, “name”:“Stan Wellback”, “title”:“Testing”, “parent”:1},
{“key”:14, “name”:“Marge Innovera”, “title”:“Hardware”, “parent”:1},
{“key”:15, “name”:“Evan Elpus”, “title”:“Quality”, “parent”:5},
{“key”:16, “name”:“Lotta B. Essen”, “title”:“Sales Rep”, “parent”:1},
{“key”:17, “name”:“Lotta B. Essen”, “title”:“Sales Rep”},
{“key”:18, “name”:“Lotta B. Essen”, “title”:“test Rep”},
{“key”:14, “name”:“Marge Innovera”, “title”:“Hardware”, “parent”:17},
{“key”:14, “name”:“Marge Innovera”, “title”:“Hardware”, “parent”:18},
];

Below is my tree structure now.

trees

if there is no child node , what icon or state should a node parallel to existing root node have.
In my previous post the nodes parallel to root node appeared to have gear like icon at root level node.

function init() {
  if (window.goSamples) goSamples();  // init for these samples -- you don't need to call this
  var $ = go.GraphObject.make;  // for conciseness in defining templates

  myDiagram =
    $(go.Palette, "myDiagramDiv",
      {
       /* allowMove: false,
        allowCopy: false,
        allowDelete: false,
        allowHorizontalScroll: false,*/
		isReadOnly: false,
        layout:
          $(go.TreeLayout,
            {
              alignment: go.TreeLayout.AlignmentStart,
              angle: 0,
              compaction: go.TreeLayout.CompactionNone,
              layerSpacing: 16,
              layerSpacingParentOverlap: 1,
              nodeIndentPastParent: 1.0,
              nodeSpacing: 0,
              setsPortSpot: false,
              setsChildPortSpot: false,
			  //isTreeExpanded: false
            })
      });

  myDiagram.nodeTemplate =
    $(go.Node,
      { // no Adornment: instead change panel background color by binding to Node.isSelected
        selectionAdorned: false,
		isTreeExpanded: false,
        // a custom function to allow expanding/collapsing on double-click
        // this uses similar logic to a TreeExpanderButton
        doubleClick: function(e, node) {
          var cmd = myDiagram.commandHandler;
          if (node.isTreeExpanded) {
            if (!cmd.canCollapseTree(node)) return;
          } else {
            if (!cmd.canExpandTree(node)) return;
          }
          e.handled = true;
          if (node.isTreeExpanded) {
				cmd.collapseTree(node);
          } else {
				 cmd.expandTree(node);
          }
        }
      },
      $("TreeExpanderButton",
        {
          "ButtonBorder.fill": "whitesmoke",
          "ButtonBorder.stroke": null,
          "_buttonFillOver": "rgba(0,128,255,0.25)",
          "_buttonStrokeOver": null
        }),
      $(go.Panel, "Horizontal",
        { position: new go.Point(18, 0) },
        new go.Binding("background", "isSelected", function(s) { return (s ? "lightblue" : "white"); }).ofObject(),
        $(go.Picture,
          {
            width: 18, height: 18,
            margin: new go.Margin(0, 4, 0, 0),
            imageStretch: go.GraphObject.Uniform
          },
          // bind the picture source on two properties of the Node
          // to display open folder, closed folder, or document
          new go.Binding("source", "isTreeExpanded", imageConverter).ofObject(),
          new go.Binding("source", "isTreeLeaf", imageConverter).ofObject()),
        $(go.TextBlock,
          { font: '12pt Verdana, sans-serif' },
		  {},
		  new go.Binding("text", "name")
         )
      ), // end Horizontal Panel
	  
	  new go.Binding("copyable", "isTreeLeaf").ofObject()
    );  // end Node

  // without lines
  myDiagram.linkTemplate = $(go.Link);
  myDiagram.contentAlignment = go.Spot.TopLeft;
   

 
  // create a random tree
  var nodeDataArray = [
  {"key":1, "name":"Stella Payne Diaz", "title":"CEO"},
  {"key":2, "name":"Luke Warm", "title":"VP Marketing/Sales", "parent":1},
  {"key":3, "name":"Meg Meehan Hoffa", "title":"Sales", "parent":1},
  {"key":4, "name":"Peggy Flaming", "title":"VP Engineering", "parent":1},
  {"key":5, "name":"Saul Wellingood", "title":"Manufacturing", "parent":3},
  {"key":6, "name":"Al Ligori", "title":"Marketing", "parent":1},
  {"key":7, "name":"Dot Stubadd", "title":"Sales Rep", "parent":4},
  {"key":8, "name":"Les Ismore", "title":"Project Mgr", "parent":5},
  {"key":9, "name":"April Lynn Parris", "title":"Events Mgr", "parent":6},
  {"key":10, "name":"Xavier Breath", "title":"Engineering", "parent":4},
  {"key":11, "name":"Anita Hammer", "title":"Process", "parent":5},
  {"key":12, "name":"Billy Aiken", "title":"Software", "parent":1},
  {"key":13, "name":"Stan Wellback", "title":"Testing", "parent":1},
  {"key":14, "name":"Marge Innovera", "title":"Hardware", "parent":1},
  {"key":15, "name":"Evan Elpus", "title":"Quality", "parent":5},
  {"key":16, "name":"Lotta B. Essen", "title":"Sales Rep", "parent":1},
  {"key":17, "name":"Lotta B. Essen", "title":"Sales Rep"},
  {"key":18, "name":"Lotta B. Essen", "title":"test Rep"},
  {"key":14, "name":"Marge Innovera", "title":"Hardware", "parent":17},
  {"key":14, "name":"Marge Innovera", "title":"Hardware", "parent":18},
   ];



  var max = nodeDataArray.length;
  var count = 0;
  while (count < max) {
    count = makeTree(1, count, max, nodeDataArray, nodeDataArray);
  }
  myDiagram.model = new go.TreeModel(nodeDataArray);
  }


function makeTree(level, count, max, nodeDataArray, parentdata) {
  //var numchildren = parentdata.numchildren;
  var numchildren=1;
  for (var i = 0; i < numchildren; i++) {
    if (count >= max) return count;
    count++;
    var childdata = { key: count, parent: parentdata.key };
    //nodeDataArray.push(childdata);
    if (level > 0 && childdata.parent) {
      count = makeTree(level - 1, count, max, nodeDataArray, childdata);
    }
  }
   return count;
}

// takes a property change on either isTreeLeaf or isTreeExpanded and selects the correct image to use
function imageConverter(prop, picture) {
  var node = picture.part;
  if (node.isTreeLeaf) {
    return "images/gear.svg";
  } else {
    if (node.isTreeExpanded) {
      return "images/folder_open.svg";
    } else {
      return "images/folder.svg";
    }
  }
}

You have changed the imageConverter function to return a gear URL for a leaf node, rather than one showing a document.

A leaf node has no children, so it is treated as a regular file. A non-leaf node has children, so it is treated as a folder/directory. If you want to treat roots specially in imageConverter, that would be fine.

Ok.

  • Is there a way I can have different fonts for Leaf Nodes and Tree Nodes.
  • Can I change the fill color of svg icons(not background color).
  1. Sure, using a binding, just as for the image choice.
  2. If you are using a Picture, no – each picture uses an HTMLImageElement and its operation is a black-box, from our point of view.
    But if you are using a Shape, sure: https://gojs.net/latest/samples/icons.html