documentationfor yFiles for HTML 2.6

TreeBuilder

Populates a graph from custom data where objects corresponding to nodes have a parent-child relationship.

Inheritance Hierarchy
TreeBuilder

Remarks

This class can be used when the data consists of one or more collections of nodes, each of which knows its child nodes, and optionally, groups. The methods createRootNodesSource, createRootGroupNodesSource, and createChildNodesSource create new source collections from which nodes and group nodes will be created.

Generally, using the TreeBuilder class consists of a few basic steps:

  1. Create a TreeBuilder and optionally, provide an IGraph on which it should operate.
    const treeBuilder = new TreeBuilder(graph)
  2. Create one or more root node sources from which the TreeBuilder creates the root nodes in the tree. Group nodes can be created by adding group node sources.
    const redData = getRootNodesData()
    // create source for root nodes (red nodes)
    const redNodesSource = treeBuilder.createRootNodesSource(redData)
  3. To create child nodes, create new sources as child sources of the root sources. By adding existing sources as child sources, the recursive structure of the tree can be defined:
    // create source for children of red nodes (blue nodes) as child source of redNodeSource
    const blueNodesSource = redNodesSource.createChildNodesSource(
      (n) => n.childrenBlue
    )
    // tie the knot
    blueNodesSource.addChildNodesSource((n) => n.childrenRed, redNodesSource)

    Edges are created by the implicit parent-child relationship between the sources. For each child node, the TreeBuilder creates an edge between the child node and its (tree) parent providing the child node data item to the parentEdgeCreator.

  4. Each TreeNodesSource<TDataItem> provides a NodeCreator<TDataItem> that allows for further specification of how the items from this source should be created. You can provide defaults for the default styling but also bind more specific styling based on the actual data item with the styleProvider and styleBindings.
    redNodesSource.nodeCreator.defaults.shareStyleInstance = false
    redNodesSource.nodeCreator.defaults.style = new ShapeNodeStyle({
      stroke: 'darkred',
      fill: 'orange'
    })
    // leaf nodes should have a diamond shape
    redNodesSource.nodeCreator.styleBindings.addBinding('shape', (redDataItem) =>
      redDataItem.childrenBlue.length > 0 ? 'roundRectangle' : 'diamond'
    )

    It also allows for obtaining layout information from the data item (layoutProvider), as well as further specification of the created node's tag (tagProvider).

  5. The edge creation can be adjusted by accessing the parentEdgeCreator that allows for specifying the styling of the created edges (defaults, styleProvider, and styleBindings).
    blueNodesSource.parentEdgeCreator.defaults.style = new PolylineEdgeStyle({
      stroke: 'cornflowerBlue'
    })

    Furthermore, it allows for obtaining bend locations from the data item (bendsProvider), as well as further specification of the created edge's tag (tagProvider).

    blueNodesSource.parentEdgeCreator.bendsProvider = (nodeDataItem) =>
      nodeDataItem.bendPoints
  6. Optionally, labels can be added by providing one or multiple label bindings. If there is a varying number of labels per node, createLabelsSource can be used, instead. Similar methods are also available on the EdgeCreator<TDataItem>.

    The LabelsSource<TDataItem> provides a LabelCreator<TDataItem> that allows for adjusting all aspects of the label creation, like style, text, size, and tag.

    const edgeLabelCreator = blueNodesSource.parentEdgeCreator.createLabelBinding(
      (blueDataItem) => blueDataItem.name
    )
    edgeLabelCreator.defaults.style = new DefaultLabelStyle({
      backgroundFill: 'rgb(225,242,253)',
      backgroundStroke: 'lightSkyBlue',
      textSize: 8
    })
  7. Call buildGraph to populate the graph. You can apply a layout algorithm afterward to make the graph look nice.
    // Build a graph initially
    treeBuilder.buildGraph()
    // Apply a layout in a subsequent step
    graph.applyLayout(new TreeLayout())
  8. If your items or collections change later, call updateGraph to make the changes visible in the graph. If the data item instances have changed, you can call setData.
    // Set the new data collections:
    treeBuilder.setData(redNodesSource, getRootNodesData())
    // Update a graph after the business data has changed
    treeBuilder.updateGraph()
    // Apply a layout in a subsequent step
    graph.applyLayout(new TreeLayout())

You can further customize how nodes, groups, and edges are created by adding event handlers to the various events and modifying the items there. This can be used to modify items in ways that are not directly supported by the available bindings or defaults. There are creation and update events for all items, which allow for separate customization when nodes, groups, and edges are created or updated. For completely static graphs, where updateGraph is not needed, the update events can be safely ignored.

Related Reading in the Developer's Guide

The different graph builders are discussed in the section Creating a Graph from Business Data. Class TreeBuilder, in particular, is topic of section TreeBuilder.

Type Details

yfiles module
view-component
yfiles-umd modules
All view modules
Legacy UMD name
yfiles.binding.TreeBuilder

See Also

This class serves as a convenient way to create trees. Some aspects to look out for:

  • buildGraph does not clear the graph. If needed, call clear to empty the graph before building it anew.
  • The TreeBuilder ignores and preserves items manually created on the graph in between calls to updateGraph.

If you need to extensively modify your data in order to fit the requirements of the TreeBuilder, it is often better to write the code interfacing with the graph by hand instead of relying on TreeBuilder.

updateGraph merely updates the graph structure. Any other bound data must be updated explicitly if necessary. Calling the respective update methods on the creators (e.g. updateStyle), resolves the provider (e.g. styleProvider) and applies the bindings (e.g. applyStyleBindings). The latter can also be applied solely.

For example, to update any aspect of node creation:
// configure the NodeCreator to update non-structural aspects
nodesSource.nodeCreator.addNodeUpdatedListener((sender, evt) => {
  nodesSource.nodeCreator.updateLayout(evt.graph, evt.item, evt.dataItem)
  nodesSource.nodeCreator.updateStyle(evt.graph, evt.item, evt.dataItem)
  nodesSource.nodeCreator.updateTag(evt.graph, evt.item, evt.dataItem)
  nodesSource.nodeCreator.updateLabels(evt.graph, evt.item, evt.dataItem)
})

builder.updateGraph()

Constructors

Properties

Methods

Events