Incremental tree grandparent node

iám trying to make an incremental tree from this link : Incremental Tree

But i have a problem, in my case i get the data with ajax. But when i click node 17 it will create new node 0. I don’t want to create node 0 again because it’s create in the beginning. So i just want to link it from node 17 to node 1.

same case with node 10 link to node 1. The case is like this picture.

Apparently your code is adding links to those nodes. Perhaps it is confused about the keys used to reference nodes in the model data?

now iam using forcedirected Layout and it works with the condition. But next problem is when I click collapse button in node 17 or node 0, all diagram is dissappeared. Please tell me how to fix it? thanks

Ok, so you really are creating cycles in your graph. That is definitely not tree-structured, which is what the “TreeExpanderButton” and CommandHandler.collapseTree expect.

You have a number of reasonable choices for what should happen when collapsing. Examine the custom behavior in Different Criteria for Hiding "Children" of Collapsed Nodes and either use its choice or implement your own variation.

“TreeExpanderButton” and CommandHandler.collapseTree expect the graph to be tree-structured. If you want to handle cycles in your graph in a different manner than it does, you need to do something different.

You have a number of reasonable choices for what should happen when collapsing. Examine the custom behavior in Different Criteria for Hiding "Children" of Collapsed Nodes and either use its choice or implement your own variation.

i cant open the link. i get confuse if i use custom expand collapse, where do i put the ajax script and then looping it. did i put the ajax in collapsefrom or expandfrom method? cause i wan to populate data when i click the button

Sorry for the typo – I have fixed the link in my previous post.

You’re going to have to understand the sample code if you want to make use of it, either unchanged or adapted for your particular app’s requirements, whatever they may be.

As is typical for our GoJS samples, the complete source code for that sample is on that page.

oke walter, iam trying to use this Different Criteria for Hiding "Children" of Collapsed Nodes. please tell me how to set the node is not collapse as a default.

// This variation on ForceDirectedLayout does not move any selected Nodes
// but does move all other nodes (vertexes).
function ContinuousForceDirectedLayout() {
go.ForceDirectedLayout.call(this);
this._isObserving = false;
}
go.Diagram.inherit(ContinuousForceDirectedLayout, go.ForceDirectedLayout);

/** @override */
ContinuousForceDirectedLayout.prototype.isFixed = function(v) {
return v.node.isSelected;
}

// optimization: reuse the ForceDirectedNetwork rather than re-create it each time
/** @override */
ContinuousForceDirectedLayout.prototype.doLayout = function(coll) {
if (!this._isObserving) {
this._isObserving = true;
// cacheing the network means we need to recreate it if nodes or links have been added or removed or relinked,
// so we need to track structural model changes to discard the saved network.
var lay = this;
this.diagram.addModelChangedListener(function (e) {
// modelChanges include a few cases that we don’t actually care about, such as
// “nodeCategory” or “linkToPortId”, but we’ll go ahead and recreate the network anyway.
// Also clear the network when replacing the model.
if (e.modelChange !== “” ||
(e.change === go.ChangedEvent.Transaction && e.propertyName === “StartingFirstTransaction”)) {
lay.network = null;
}
});
}
var net = this.network;
if (net === null) { // the first time, just create the network as normal
this.network = net = this.makeNetwork(coll);
} else { // but on reuse we need to update the LayoutVertex.bounds for selected nodes
this.diagram.nodes.each(function (n) {
var v = net.findVertex(n);
if (v !== null) v.bounds = n.actualBounds;
});
}
// now perform the normal layout
go.ForceDirectedLayout.prototype.doLayout.call(this, coll);
// doLayout normally discards the LayoutNetwork by setting Layout.network to null;
// here we remember it for next time
this.network = net;
}
// end ContinuousForceDirectedLayout

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

 myDiagram =
  $(go.Diagram, "myDiagramDiv",  // must name or refer to the DIV HTML element
    {
	  "toolManager.mouseWheelBehavior": go.ToolManager.WheelZoom,
      initialAutoScale: go.Diagram.Uniform,  // an initial automatic zoom-to-fit
      contentAlignment: go.Spot.Center,  // align document to the center of the viewport
      layout:
        $(ContinuousForceDirectedLayout,  // automatically spread nodes apart while dragging
          { defaultSpringLength: 30, defaultElectricalCharge: 100 }),
      // do an extra layout at the end of a move
      "SelectionMoved": function(e) { e.diagram.layout.invalidateLayout(); }
    });

// dragging a node invalidates the Diagram.layout, causing a layout during the drag
myDiagram.toolManager.draggingTool.doMouseMove = function() {
  go.DraggingTool.prototype.doMouseMove.call(this);
  if (this.isActive) { this.diagram.layout.invalidateLayout(); }
}

  
myDiagram.nodeTemplate =
$(go.Node, go.Panel.Vertical,
	{ portId: "", fromLinkable: true, toLinkable: true },
	$(go.Panel, go.Panel.Auto,
		$(go.Shape,
			{ fill: "white", minSize: new go.Size(30, 30), strokeWidth: 0 },
			{ cursor: "pointer" },  // indicate that linking may start here
			new go.Binding("fill", "warnanode")
		),
		$(go.TextBlock,
			{ margin: 2 },
			{ fromLinkable: false, toLinkable: false },  // don't start drawing a link from the text
			new go.Binding("text", "text")
		)
	),
	$("Button",  // a replacement for "TreeExpanderButton" that works for non-tree-structured graphs
		// assume initially not visible because there are no links coming out
		{ visible: false },
		// bind the button visibility to whether it's not a leaf node
		new go.Binding("visible", "isTreeLeaf", function(leaf) { return !leaf; }) .ofObject(),
		$(go.Shape,
			{
				name: "ButtonIcon",
				figure: "MinusLine",
				desiredSize: new go.Size(6, 6)
			},
			new go.Binding("figure", "isCollapsed",  // data.isCollapsed remembers "collapsed" or "expanded"
			function(collapsed) { return collapsed ? "PlusLine" : "MinusLine"; })
		),
		{
			click: function(e, obj) {
				e.diagram.startTransaction();
				var node = obj.part;
				if (node.data.isCollapsed) {
				  expandFrom(node, node);
				} else {
				  collapseFrom(node, node);
				}
				e.diagram.commitTransaction("toggled visibility of dependencies");
			}
		}
	)
);

function collapseFrom(node, start) {
	if (node.data.isCollapsed) return;
	node.diagram.model.setDataProperty(node.data, "isCollapsed", true);
	if (node !== start) node.visible = false;
	
	node.findNodesOutOf().each(collapseFrom);
}

function expandFrom(node, start) {
	if (!node.data.isCollapsed) return;
	node.diagram.model.setDataProperty(node.data, "isCollapsed", false);
	if (node !== start) node.visible = true;
	
	node.findNodesOutOf().each(expandFrom);
}

// replace the default Link template in the linkTemplateMap
myDiagram.linkTemplate =
  $(go.Link,  // the whole link panel
    $(go.Shape,  // the link shape
      { stroke: "black", strokeWidth: 2},
	  new go.Binding("stroke", "warnagarislink")),
    $(go.Shape,  // the arrowhead
      { fromArrow: "BackwardOpenTriangle", stroke: "black", fill: "black"},
	  new go.Binding("strokeWidth", "tebalgaris"),
	  new go.Binding("stroke", "warnagaris"),
	  new go.Binding("fill", "warna")),
    $(go.Panel, "Auto",
      $(go.Shape,  // the link shape
        { fill: $(go.Brush, "Radial", { 0: "rgb(240, 240, 240)", 0.3: "rgb(240, 240, 240)", 1: "rgba(240, 240, 240, 0)" }),
          stroke: null }),
      $(go.TextBlock,  // the label
        { textAlign: "center",
          font: "10pt helvetica, arial, sans-serif",
          stroke: "black",
          margin: 3},
        new go.Binding("text", "linktext"),
        new go.Binding("stroke", "warnatextlink")
  )
    )
  );

myDiagram.model.nodeDataArray = [{key: "A", text:"Text A", warnanode:"green"}];
myDiagram.model.addNodeData({ key: "B", text:"Text B", warnanode:"orange" });
myDiagram.model.addNodeData({ key: "C", text:"Text C", warnanode:"orange" });
myDiagram.model.addNodeData({ key: "D", text:"Text D", warnanode:"orange" });
myDiagram.model.addNodeData({ key: "E", text:"Text E", warnanode:"orange" });
myDiagram.model.addNodeData({ key: "F", text:"Text F", warnanode:"orange" });

myDiagram.model.addLinkData({ from: "A", to:"B", linktext:"link A ke B" });
myDiagram.model.addLinkData({ from: "A", to:"C", linktext:"link A ke C" });
myDiagram.model.addLinkData({ from: "A", to:"D", linktext:"link A ke D" });
myDiagram.model.addLinkData({ from: "A", to:"E", linktext:"link A ke E" });
myDiagram.model.addLinkData({ from: "E", to:"A", linktext:"link E ke A" });
myDiagram.model.addLinkData({ from: "E", to:"F", linktext:"link E ke F" });
myDiagram.model.addLinkData({ from: "F", to:"A", linktext:"link F ke A" }); 

all I want is collapse all nodes except node A. when page first load it just node A with button plus, when i click plus it will expand node

On a glance at your code I don’t see why any nodes should be collapsed. You’ll have to look carefully at it to see how it’s meaningfully different from Different Criteria for Hiding "Children" of Collapsed Nodes.

Wait – you seem to be asking for contradictory initial states. By default all nodes will be visible. If you want a particular node to be collapsed, you’ll need to collapse it explicitly by calling collapseFrom.

i mean with my code, the default is all nodes visible. what i want is only node a visible. when i click button plus it will visible node that link to node a. how to set visible just node a?

Yes, I misinterpreted your intent when you said:

What I think you want is that the nodes connected from node A are not visible, whether or not they are collapsed.

Did calling collapseFrom on node A not do what you want?

i dont know how to calling collapsefrom on node a. can you give me an example?

What have you tried? What results are you getting, and how are they different from what you want?

my code is like this

// This variation on ForceDirectedLayout does not move any selected Nodes
// but does move all other nodes (vertexes).
function ContinuousForceDirectedLayout() {
go.ForceDirectedLayout.call(this);
this._isObserving = false;
}
go.Diagram.inherit(ContinuousForceDirectedLayout, go.ForceDirectedLayout);

/** @override */
ContinuousForceDirectedLayout.prototype.isFixed = function(v) {
return v.node.isSelected;
}

// optimization: reuse the ForceDirectedNetwork rather than re-create it each time
/** @override */
ContinuousForceDirectedLayout.prototype.doLayout = function(coll) {
if (!this._isObserving) {
this._isObserving = true;
// cacheing the network means we need to recreate it if nodes or links have been added or removed or relinked,
// so we need to track structural model changes to discard the saved network.
var lay = this;
this.diagram.addModelChangedListener(function (e) {
// modelChanges include a few cases that we don’t actually care about, such as
// “nodeCategory” or “linkToPortId”, but we’ll go ahead and recreate the network anyway.
// Also clear the network when replacing the model.
if (e.modelChange !== “” ||
(e.change === go.ChangedEvent.Transaction && e.propertyName === “StartingFirstTransaction”)) {
lay.network = null;
}
});
}
var net = this.network;
if (net === null) { // the first time, just create the network as normal
this.network = net = this.makeNetwork(coll);
} else { // but on reuse we need to update the LayoutVertex.bounds for selected nodes
this.diagram.nodes.each(function (n) {
var v = net.findVertex(n);
if (v !== null) v.bounds = n.actualBounds;
});
}
// now perform the normal layout
go.ForceDirectedLayout.prototype.doLayout.call(this, coll);
// doLayout normally discards the LayoutNetwork by setting Layout.network to null;
// here we remember it for next time
this.network = net;
}
// end ContinuousForceDirectedLayout

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

 myDiagram =
  $(go.Diagram, "myDiagramDiv",  // must name or refer to the DIV HTML element
    {
	  "toolManager.mouseWheelBehavior": go.ToolManager.WheelZoom,
      initialAutoScale: go.Diagram.Uniform,  // an initial automatic zoom-to-fit
      contentAlignment: go.Spot.Center,  // align document to the center of the viewport
      layout:
        $(ContinuousForceDirectedLayout,  // automatically spread nodes apart while dragging
          { defaultSpringLength: 30, defaultElectricalCharge: 100 }),
      // do an extra layout at the end of a move
      "SelectionMoved": function(e) { e.diagram.layout.invalidateLayout(); }
    });

// dragging a node invalidates the Diagram.layout, causing a layout during the drag
myDiagram.toolManager.draggingTool.doMouseMove = function() {
  go.DraggingTool.prototype.doMouseMove.call(this);
  if (this.isActive) { this.diagram.layout.invalidateLayout(); }
}

  
myDiagram.nodeTemplate =
$(go.Node, go.Panel.Vertical,
	{ portId: "", fromLinkable: true, toLinkable: true },
	$(go.Panel, go.Panel.Auto,
		$(go.Shape,
			{ fill: "white", minSize: new go.Size(30, 30), strokeWidth: 0 },
			{ cursor: "pointer" },  // indicate that linking may start here
			new go.Binding("fill", "warnanode")
		),
		$(go.TextBlock,
			{ margin: 2 },
			{ fromLinkable: false, toLinkable: false },  // don't start drawing a link from the text
			new go.Binding("text", "text")
		)
	),
	$("Button",  // a replacement for "TreeExpanderButton" that works for non-tree-structured graphs
		// assume initially not visible because there are no links coming out
		{ visible: false },
		// bind the button visibility to whether it's not a leaf node
		new go.Binding("visible", "isTreeLeaf", function(leaf) { return !leaf; }) .ofObject(),
		$(go.Shape,
			{
				name: "ButtonIcon",
				figure: "MinusLine",
				desiredSize: new go.Size(6, 6)
			},
			new go.Binding("figure", "isCollapsed",  // data.isCollapsed remembers "collapsed" or "expanded"
			function(collapsed) { return collapsed ? "PlusLine" : "MinusLine"; })
		),
		{
			click: function(e, obj) {
				e.diagram.startTransaction();
				var node = obj.part;
				if (node.data.isCollapsed) {
				  expandFrom(node, node);
				} else {
				  collapseFrom(node, node);
				}
				e.diagram.commitTransaction("toggled visibility of dependencies");
			}
		}
	)
);

function collapseFrom(node, start) {
	if (node.data.isCollapsed) return;
	node.diagram.model.setDataProperty(node.data, "isCollapsed", true);
	if (node !== start) node.visible = false;
	
	node.findNodesOutOf().each(collapseFrom);
}

function expandFrom(node, start) {
	if (!node.data.isCollapsed) return;
	node.diagram.model.setDataProperty(node.data, "isCollapsed", false);
	if (node !== start) node.visible = true;
	
	node.findNodesOutOf().each(expandFrom);
}

// replace the default Link template in the linkTemplateMap
myDiagram.linkTemplate =
  $(go.Link,  // the whole link panel
    $(go.Shape,  // the link shape
      { stroke: "black", strokeWidth: 2},
	  new go.Binding("stroke", "warnagarislink")),
    $(go.Shape,  // the arrowhead
      { fromArrow: "BackwardOpenTriangle", stroke: "black", fill: "black"},
	  new go.Binding("strokeWidth", "tebalgaris"),
	  new go.Binding("stroke", "warnagaris"),
	  new go.Binding("fill", "warna")),
    $(go.Panel, "Auto",
      $(go.Shape,  // the link shape
        { fill: $(go.Brush, "Radial", { 0: "rgb(240, 240, 240)", 0.3: "rgb(240, 240, 240)", 1: "rgba(240, 240, 240, 0)" }),
          stroke: null }),
      $(go.TextBlock,  // the label
        { textAlign: "center",
          font: "10pt helvetica, arial, sans-serif",
          stroke: "black",
          margin: 3},
        new go.Binding("text", "linktext"),
        new go.Binding("stroke", "warnatextlink")
  )
    )
  );

myDiagram.model.nodeDataArray = [{key: "A", text:"Text A", warnanode:"green"}];
myDiagram.model.addNodeData({ key: "B", text:"Text B", warnanode:"orange" });
myDiagram.model.addNodeData({ key: "C", text:"Text C", warnanode:"orange" });
myDiagram.model.addNodeData({ key: "D", text:"Text D", warnanode:"orange" });
myDiagram.model.addNodeData({ key: "E", text:"Text E", warnanode:"orange" });
myDiagram.model.addNodeData({ key: "F", text:"Text F", warnanode:"orange" });

myDiagram.model.addLinkData({ from: "A", to:"B", linktext:"link A ke B" });
myDiagram.model.addLinkData({ from: "A", to:"C", linktext:"link A ke C" });
myDiagram.model.addLinkData({ from: "A", to:"D", linktext:"link A ke D" });
myDiagram.model.addLinkData({ from: "A", to:"E", linktext:"link A ke E" });
myDiagram.model.addLinkData({ from: "E", to:"A", linktext:"link E ke A" });
myDiagram.model.addLinkData({ from: "E", to:"F", linktext:"link E ke F" });
myDiagram.model.addLinkData({ from: "F", to:"A", linktext:"link F ke A" }); 

that codes will result all nodes visible.

but all i want is just node a is visible. when i click node a it will reveal child node of node a

But you haven’t even tried to call collapseFrom.

var node = myDiagram.findNodeForKey("A");
if (node !== null) collapseFrom(node, node);