Tree Data Model

Overview

The tree data model represents data as a hierarchical tree-like structure with data items connected by parent–child relationships.

It is used in the following chart types:

This article explains how to set tree-like data, access data items, and perform operations on data.

Classes

Here is the list of classes allowing you to work with tree data in AnyChart:

Quick Start

To create a chart with tree-like data, create a data tree by passing your data to the anychart.data.tree() method with "as-tree" as the second parameter. Then pass the tree to the chart constructor:

// create data
var data = [
  {name:   "Root", children: [
    {name:   "Child 1", value: 65511098},
    {name:   "Child 2", value: 64938716},
    {name:   "Child 3", value: 59797978},
    {name:   "Child 4", value: 46070146}
  ]}
];

// create a data tree
var treeData = anychart.data.tree(data, "as-tree");

// create a chart and set the data
var chart = anychart.treeMap(treeData);

// set the container id
treemap.container("container");

// initiate drawing the chart
treemap.draw();

The following sample shows how to create different chart types with the same tree-like data:

Playground

Setting Data

Tree data structures in Anychart are defined as instances of the anychart.data.Tree class, and data items are defined as instances of anychart.data.Tree.DataItem.

To create a chart based on tree-like data, you should organize your data either as a tree or as a table. Also, you can use a CSV string (see also: Data from CSV). Then the data is processed by the component, and an instance of anychart.data.Tree is created.

1. Creating Data Tree. The first step is passing your data to the anychart.data.tree() method with "as-tree" or "as-table" as the second parameter:

treeData = anychart.data.tree(data, "as-tree");
treeData = anychart.data.tree(data, "as-table");

If your data is a CSV string, you should pass a CSV mapping object as the second parameter. Read more in the CSV String section.

2. Creating Chart. Then pass the instance of the anychart.data.Tree class created by this method to the chart constructor:

var chart = anychart.treeMap(treeData);

You can as well skip the first step and pass your data to the data() method of the chart or directly to the chart constructor, also with the "as-tree" or "as-table" parameter. In this case the instance of anychart.data.tree() is created implicitly (to get it, use the data() method of the chart).

3. Data Fields. The choice of data fields depends on the chart type and on the way your data is structured. If the data is organized as a tree, the children field is always required. If it is organized as a table or a CSV string, id and parent are required – they are used to specify the hierarchy of elements.

Note 1: To learn how to rename the default fields of the tree data model (children, parent, id) or map custom fields, see the Mapping section.

Note 2: The id field is required for the live edit mode of the Gantt Chart. To learn more, read the the Live Edit UI and API article and take a look at the sample in the Events section of this article.

As Tree

This sample shows how to set data if it data is organized as a tree:

// create data
var data = [
  {name:     "Root", children: [
    {name:   "Parent 1", children: [
      {name: "Child 1-1", value: 150000000},
      {name: "Child 1-2", value:  45000000},
      {name: "Child 1-3", value:   3200000}
    ]},
    {name:   "Parent 2", children: [
      {name: "Child 2-1", value:  55000000},
      {name: "Child 2-2", value:  10600000},
      {name: "Child 2-3", value:   5200000}
    ]},
    {name:   "Parent 3", children: [
      {name: "Child 3-1", value:  21000000},
      {name: "Child 3-2", value:   9000000}
    ]}  
  ]} 
];

// create a data tree
treeData = anychart.data.tree(data, "as-tree");

// create a chart and set the data
var chart = anychart.treeMap(treeData);

Playground

As Table

In the following sample data is organized as a table:

// create data
var data = [
  {id:  1, parent: null, name: "Root"},
  {id:  2, parent:    1, name: "Parent 1"},
  {id:  3, parent:    2, name: "Child 1-1", value: 150000000},
  {id:  4, parent:    2, name: "Child 1-2", value:  45000000},
  {id:  5, parent:    2, name: "Child 1-3", value:   3200000},
  {id:  6, parent:    1, name: "Parent 2"},
  {id:  7, parent:    6, name: "Child 2-1", value:  55000000},
  {id:  8, parent:    6, name: "Child 2-2", value:  10600000},
  {id:  9, parent:    6, name: "Child 2-3", value:   5200000},
  {id: 10, parent:    1, name: "Parent 3"},
  {id: 11, parent:   10, name: "Child 3-1", value:  21000000},
  {id: 12, parent:   10, name: "Child 3-2", value:   9000000}
];

// create a data tree
treeData = anychart.data.tree(data, "as-table");

// create a chart and set the data
var chart = anychart.treeMap(treeData);

Playground

CSV String

To set data as a CSV string, call the anychart.data.tree() method with the following parameters:

  • a CSV string
  • an object with CSV mapping
  • an object with CSV settings (optional)

Note 1: The structure of your data should be similar to data set as a table: specify the hierarchy of elements by mapping the id and parent fields (the choice of other fields depends on the chart type).

Note 2: By default, AnyChart considers commas in CSV data to be column separators and line breaks to be row separators, but you can specify alternative settings in an object and pass it as the third parameter. Use the columnsSeparator and rowsSeparator fields to set separators and ignoreFirstRow to ignore the first row of the table if needed.

See also: Data from CSV.

The sample below shows how to set data as a CSV string:

// create data
var data = "id;parent;name;value*" +
           "1;null;Root*"+
           "2;1;Parent 1*" +
           "3;2;Child 1-1;150000000*" +
           "4;2;Child 1-2;45000000*" +
           "5;2;Child 1-3;3200000*" +
           "6;1;Parent 2;*" +
           "7;6;Child 2-1;55000000*" +
           "8;6;Child 2-2;10600000*" +
           "9;6;Child 2-3;5200000*" +
           "10;1;Parent 3;*" +
           "11;10;Child 3-1;21000000*" +
           "12;10;Child 3-2;9000000*";

// create an object with a csv mapping
csvMapping = {"id": 0, "parent": 1, "name": 2, "value": 3};

// create an object with csv settings
csvSettings = {ignoreFirstRow: true, columnsSeparator: ";", rowsSeparator: "*"};

// create a data tree
var treeData = anychart.data.tree(data, csvMapping, csvSettings);

// create a chart and set the data
var chart = anychart.treeMap(treeData);

Playground

Mapping

In case you need to map your data, call the mapAs method on the instance of anychart.data.Tree. Then pass the mapped data to the chart constructor or to the data() method of the chart.

The mapAs method allows you to map any field fields except the fields required by the tree data model – children, parent, id. Instead, you should use the anychart.data.tree() constructor.

If you set data as a tree or as a table, pass the mapping as the fourth parameter. Please note that the third one should be set to null – it is used only with CSV data to specify CSV settings. The mapping for CSV data is passed as the second parameter.

In the following sample, the data is set as a tree. The anychart.data.tree() constructor is used to map a custom field child_items as the children field required by the tree data model. The mapAs method maps start and end as actualStart and actualEnd required by the Gantt chart:

// create data
var data = [
  {
    name:   "Root",
    start: Date.UTC(2018, 0, 25),
    end: Date.UTC(2018, 2, 14),
    child_items: [
      {
        name:   "Child 1",
        start: Date.UTC(2018, 0, 25),
        end: Date.UTC(2018, 1, 3)
      },
      {
        name:   "Child 2",
        start: Date.UTC(2018, 1, 4),
        end: Date.UTC(2018, 1, 4)
      },
      {
        name:   "Child 3",
        start: Date.UTC(2018, 1, 4),
        end: Date.UTC(2018, 1, 24)
      },
      {
        name:   "Child 4",
        start: Date.UTC(2018, 1, 24),
        end: Date.UTC(2018, 2, 14)
      }
    ]
}];

// create a data tree
var treeData = anychart.data.tree(data, "as-tree", null, {children: "child_items"});

// map the data
var mapping = treeData.mapAs({actualStart: "start", actualEnd: "end"});

// create a chart
chart = anychart.ganttProject();

// set the data
chart.data(mapping);

Playground

Accessing Items

Data items in AnyChart are defined as instances of the anychart.data.Tree.DataItem class. If you need to access them, you can either search for them or call special methods.

To access items at the root level, use the following methods of anychart.data.Tree:

To go deeper, use methods of anychart.data.Tree.DataItem:

For example, this is how you get the sixth child of the third child of the first root item:

treeData.getChildAt(0).getChildAt(2).getChildAt(5);

Manipulating data very often requires accessing data items, so the methods listed above are used in most samples in the Data Manipulation section.

Data Manipulation

You can perform the following data operations:

Reading

You can read the value of an item's data field with a given name: access the instance of anychart.data.Tree.DataItem and use the get() method.

In the sample below, this method is used to display the name of the last child in the title of the chart:

// get the name of the last child
var lastChild = treeData.getChildAt(0).getChildren().length - 1;
var lastChildName = treeData.getChildAt(0).getChildAt(lastChild).get("name");

Playground

Adding

You can add a root item to your data: call the addChild() or addChildAt() method on the instance of anychart.data.Tree. Please note that the second method adds an item with a given index.

To add a child element to a data item, access the instance of anychart.data.Tree.DataItem and call addChild() or addChildAt() on it:

var itemCount = 1;

// add a new data item
function addItem(){
  var name = "New Child " + itemCount++;
  treeData.getChildAt(0).addChild({"name": name, "value": 10000000});
};

Playground

You can also add several root items at once: use the addData() method.

Note: Only one root element can be displayed on the Treemap chart, so using this method does not change the way the Treemap looks, though the data is updated anyway.

Here is a Sunburst chart with a button adding two root nodes at a time:

var itemCount = 1;

// add new data
function addItems(){
  //create new data
  var name_1 = "New Node " + itemCount++;
  var name_2 = "New Node " + itemCount++;
  var newData = [
    {"name": name_1, "value": 10000000},
    {"name": name_2, "value": 10000000}
  ];
  // add new data
  treeData.addData(newData, "as-tree");
};

Playground

Updating

To update a data field of an item, access the instance of anychart.data.Tree.DataItem and call set(). Use the name of the field and a new value as parameters:

// update the first child
function updateItem(){
  var name = document.getElementById("inputName").value;
  var value = document.getElementById("inputValue").value;
  var color = document.getElementById("inputColor").value;
  treeData.getChildAt(0).getChildAt(0).set("name", name);
  treeData.getChildAt(0).getChildAt(0).set("value", value);
  treeData.getChildAt(0).getChildAt(0).set("fill", color);
};

Playground

Removing

To remove root items from your data, call one of the following methods on the instance of anychart.data.Tree:

To remove a child of a data item, access the instance of anychart.data.Tree.DataItem and call one of these methods:

In this sample the current last child of the root item is removed each time you press the button:

var lastChild = treeData.getChildAt(0).getChildren().length - 1;
treeData.getChildAt(0).removeChildAt(lastChild);

Playground

Searching

To search for an item, use the following methods of the anychart.data.Tree class:

search()

The search() method returns either an array of data items or one item, while searchItems() always returns an array. Both methods are called with three parameters: the name of a data field, a value, and a comparison function.

In the next sample search(), combined with the drillTo method of the Treemap, is used to find an item with a certain name and drill down to it:

/* locate an item in the data tree
and get it as an object */
var item = treeData.search("name", "Item 3-4");

// drill down to the item
chart.drillTo(item);

Playground

The comparison function accepts the name of a data field and a value and returns a negative number, zero, or positive number.

The following sample shows how to perform a search with the searchItems() method and a comparison function, which is used to access properties of objects in the custom data field employee:

// create data
var data = [
  {
    name:   "Root",
    actualStart: Date.UTC(2018, 0, 25),
    actualEnd: Date.UTC(2018, 2, 14),
    employee: {firstName: null, lastName: null},
    children: [
      {
        name:   "Child 1",
        actualStart: Date.UTC(2018, 0, 25),
        actualEnd: Date.UTC(2018, 1, 3),
        employee: {firstName: "John", lastName: "Doe"}
      },
      {
        name:   "Child 2",
        actualStart: Date.UTC(2018, 1, 4),
        actualEnd: Date.UTC(2018, 1, 4),
        employee: {firstName: "Frank", lastName: "Foe"}
      },
      {
        name:   "Child 3",
        actualStart: Date.UTC(2018, 1, 4),
        actualEnd: Date.UTC(2018, 1, 24),
        employee: {firstName: "John", lastName: "Doe"}
      },
      {
        name:   "Child 4",
        actualStart: Date.UTC(2018, 1, 24),
        actualEnd: Date.UTC(2018, 2, 14),
        employee: {firstName: "Marta", lastName: "Moe"}
      }
    ]
}];

// create a data tree
treeData = anychart.data.tree(data, "as-tree");

// create a gantt chart
chart = anychart.ganttProject();

// set the data
chart.data(treeData);

// a comparison function
function comparisonFunction(fieldValue, comparisonValue) {
  if (comparisonValue == fieldValue.firstName + fieldValue.lastName) {
    return 0;
  } else {
    return 1;
  }
};

// search for items
var items = treeData.searchItems("employee", "JohnDoe", comparisonFunction);

Playground

filter()

The filter() method returns an array of data items. It is always called with a filter function as a parameter, which accepts a data item and returns true or false.

Use this method to set advanced search conditions, for example to find all elements greater or less than a given value or to compare two data fields, like in the sample below.

In this sample a filter function is used to find items with duration greater than a given one, duration being calculated from two data fields (the names of these items are displayed in the title of the chart, and their nodes are colored):

// search for items with duration equal or greater than a given one
var inputValue = (document.getElementById("inputValue").value) * 1000 * 3600 * 24;
var items = treeData.filter(function(item) {
  return item.get("actualEnd") - item.get("actualStart") >= inputValue;
});

Playground

Indexes

Some operations are performed faster on indexed data. To create an index on a data field, call the createIndexOn() on the instance of anychart.data.Tree and specify the name of the field as a parameter:

// create an index
treeData.createIndexOn("value");

Note: You cannot create an index on the parent or child field.

To remove the index on a field, use removeIndexOn() with the name of the field as a parameter:

// remove the index
treeData.removeIndexOn("value");

Traversing

Traversing is a process of going through all the items of a tree. You can access them directly, but AnyChart offers an easier and faster out-of-the-box solution.

To perform a traversal, use the getTraverser() method to obtain the anychart.data.Traverser object. Then call its methods:

  • advance() – advances the traverser to the next data item
  • current() – returns the current item
  • get() – returns the current item's value in a given data field
  • getDepth() – returns the depth of the current item
  • meta() – sets/gets the meta value of the current item
  • nodeYieldCondition() – sets/gets a function that determines whether an item is returned
  • set() – sets the value of the current item in a given data field
  • reset() – resets the traverser to its default position before the first item
  • toArray() – returns the current traverser as an array of data items
  • traverseChildrenCondition() – sets/gets a function that determines whether the traverser goes through the children of an item

In the sample below the advance() and get() methods are used to display the names of all the data items:

// get the traverser of a tree
var traverser = treeData.getTraverser();

/* get the element displaying information about the tree */
var treeInfo = document.getElementById("treeInfo");

// display the names of all data items in the tree
while (traverser.advance()) {
  var newElement = document.createElement("li");
  newElement.innerText = traverser.get("name");
  treeInfo.appendChild(newElement);
};

Playground

In the next sample advance() and current(), combined with the drillTo method of the Treemap, are used to drill down through all the nodes of the chart. The reset() method allows starting the traversal again when it is finished.

// get the traverser of a tree
traverser = treeData.getTraverser();

// skip the root node
traverser.advance();

// get the next data item and drill to it
function nextItem() {
  // try to go to the next item
  if (traverser.advance()) {
    /* get the current item
    as an instance of the dataItem class */
    var dataItem = traverser.current();
    // drill down to the item
    chart.drillTo(dataItem);
  }
  else {
    //reset the traverser
    traverser.reset();
  }
};

Playground

Events

Here is the full list of events that work with the tree data model:

ValueDescription
treeItemCreate item created
treeItemMoveitem moved
treeItemRemoveitem removed
treeItemUpdateitem updated

Please note that you can not only listen to events, but also stop or start dispatching them by calling the dispatchEvents() method with true or false as a parameter.

In the sample below, there is a Gantt chart with the editing mode enabled: you can use the mouse to update items (change the position, duration, name, etc). Also, there is a button for adding items. Even listeners are used to update the chart title whenever an item is updated or added:

// update the chart title when an item is updated
treeData.listen("treeItemUpdate", function (e) {
  var itemName = e.item.get("name");
  chart.title().useHtml(true);
  chart.title("Tree Data Model: Events<br><br>" +
              "<span style = 'color:#990000'>" +
              itemName + "</span> updated");
});

// update the chart title when an item is added
treeData.listen("treeItemCreate", function (e) {
  var itemName = e.item.get("name");
  chart.title().useHtml(true);
  chart.title("Tree Data Model: Events<br><br>" +
              "<span style = 'color:#990000'>" +
              itemName + "</span> added");
});

Playground