All Components

Data Binding

The Chart supports binding data series and the category axis to arrays and Observables.

Binding Series

This section provides information on the binding methods for the Chart series in general.

For more information on how to configure each kind of series, refer to the article on series types.

Array of Values

The simplest form of data binding involves the supplying of each series with an array of values.

@Component({
    selector: 'my-app',
    template: `
        <kendo-chart>
          <kendo-chart-series>
            <kendo-chart-series-item [data]="seriesData">
            </kendo-chart-series-item>
          </kendo-chart-series>
        </kendo-chart>
    `
})
class AppComponent {
    private seriesData: number[] = [1, 2, 3, 5];
}

Array of Arrays

Some series require more than one value per point—for example, the Scatter (x and y) and Bubble (x, y and size) series.

The following example demonstrates how to bind a Bubble series to an array of arrays.

@Component({
    selector: 'my-app',
    template: `
        <kendo-chart>
          <kendo-chart-series>
            <kendo-chart-series-item type="bubble" [data]="seriesData">
            </kendo-chart-series-item>
          </kendo-chart-series>
        </kendo-chart>
    `
})
class AppComponent {
    private seriesData: number[] = [[1, 1, 10], [2, 2, 20], [3, 3, 30]];
}

Objects

The Chart allows you to bind to objects by specifying the fields you want to use—for value, category, X value, Y value, and so on.

This is the most commonly used type of binding as it allows you to use your model with little or no modification.

The following example demonstrates how to configure a Column series with bound category text and a value:

interface Model {
    product: string;
    sales: number;
}

@Component({
    selector: 'my-app',
    template: `
        <kendo-chart>
          <kendo-chart-series>
            <kendo-chart-series-item
                type="column" [data]="seriesData"
                field="sales" categoryField="product">
            </kendo-chart-series-item>
          </kendo-chart-series>
        </kendo-chart>
    `
})
class AppComponent {
    private seriesData: Model[] = [{
        product: "Chai",
        sales: 200
    }, {
        product: "Others",
        sales: 250
    }];
}

Observables

Binding to Observables is possible by using an async pipe.

The Chart updates the series every time new data is published.

import { Component } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/interval';
import 'rxjs/add/observable/from';
import 'rxjs/add/operator/bufferCount';
import 'rxjs/add/operator/map';

@Component({
    selector: 'my-app',
    template: `
        <kendo-chart [transitions]="false">
          <kendo-chart-series>
            <kendo-chart-series-item
                type="column" [data]="seriesData | async">
            </kendo-chart-series-item>
          </kendo-chart-series>
        </kendo-chart>
    `
})
export class AppComponent {
    /* Start with an empty observable */
    public seriesData: Observable<number[]>;

    constructor() {
        /* Produce 1 random value each 100ms
           and emit it in batches of 10. */
        this.seriesData = Observable.interval(100)
            .map(i => Math.random())
            .bufferCount(10);
    }
}

Binding Categories

The category axis of Categorical Charts is a data bound component just like the series.

It supports two main ways to provide the category list:

  • Through arrays of labels
  • Through category fields

Array of Labels

The simplest form of data binding involves the supplying of an array of labels for the categories to the axis.

The list will be displayed as is, without any modification. Series data points are positioned in sequence along the axis.

  • The order of the categories has no relation to the order of series data points.
  • The number of the categories has to equal the number of data points in the series.
  • To preserve the order, the missing values in the series have to be represented by null.
@Component({
    selector: 'my-app',
    template: `
        <kendo-chart>
          <kendo-chart-category-axis>
            <kendo-chart-category-axis-item [categories]="categories">
            </kendo-chart-category-axis-item>
          </kendo-chart-category-axis>
          <kendo-chart-series>
            <kendo-chart-series-item [data]="seriesData">
            </kendo-chart-series-item>
          </kendo-chart-series>
        </kendo-chart>
    `
})
class AppComponent {
    private seriesData: number[] = [20, 40, 45, 30, 50];
    private categories: string[] = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'];
}

Category Field

The approach above is error-prone because of the restriction of having to maintain a category and data order.

To avoid this behavior, bind the categories to the same model object as the series. In this way, it is automatically guaranteed that the series points and categories will always match.

interface Model {
    product: string;
    sales: number;
}

@Component({
    selector: 'my-app',
    template: `
        <kendo-chart>
          <kendo-chart-series>
            <kendo-chart-series-item
                type="column" [data]="seriesData"
                field="sales" categoryField="product">
            </kendo-chart-series-item>
          </kendo-chart-series>
        </kendo-chart>
    `
})
class AppComponent {
    private seriesData: Model[] = [{
        product: "Chai",
        sales: 200
    }, {
        product: "Others",
        sales: 250
    }];
}

Category Aggregates

Binding to a category field raises an interesting problem when two data points have the same category.

Consider the example below that demonstrates two values declared for 'Chai'.

interface Model {
    product: string;
    sales: number;
}

@Component({
    selector: 'my-app',
    template: `
        <kendo-chart>
          <kendo-chart-series>
            <kendo-chart-series-item
                type="column" [data]="seriesData"
                field="sales" categoryField="product">
            </kendo-chart-series-item>
          </kendo-chart-series>
        </kendo-chart>
    `
})
class AppComponent {
    private seriesData: Model[] = [{
        product: "Chai",
        sales: 200
    }, {
        product: "Chai",
        sales: 100
    }, {
        product: "Others",
        sales: 250
    }];
}

In this case, the Chart takes the data points from the source data set and produces a new point using an aggregate function.

The aggregate function is executed for all data points when the category binding is in use.

By default, the aggregate function returns the maximum value of the value fields. If the category contains only one point, it returns it without modification.

Other aggregates, such as count and sum, produce their own value even if the category contains just one data point.

interface Model {
    product: string;
    sales: number;
}

@Component({
    selector: 'my-app',
    template: `
        <kendo-chart>
          <kendo-chart-series>
            <kendo-chart-series-item
                aggregate="count"
                type="column" [data]="seriesData"
                field="sales" categoryField="product">
            </kendo-chart-series-item>
          </kendo-chart-series>
        </kendo-chart>
    `
})
class AppComponent {
    private seriesData: Model[] = [{
        product: "Chai",
        sales: 200
    }, {
        product: "Chai",
        sales: 100
    }, {
        product: "Others",
        sales: 250
    }];
}

It is also possible to define your own aggregate functions, as demonstrated in the example below.

interface Model {
    product: string;
    sales: number;
}

@Component({
    selector: 'my-app',
    template: `
        <kendo-chart>
          <kendo-chart-series>
            <kendo-chart-series-item
                [aggregate]="myAggregate"
                type="column" [data]="seriesData"
                field="sales" categoryField="product">
            </kendo-chart-series-item>
          </kendo-chart-series>
        </kendo-chart>
    `
})
class AppComponent {
    private seriesData: Model[] = [{
        product: "Chai",
        sales: 200
    }, {
        product: "Chai",
        sales: 100
    }, {
        product: "Others",
        sales: 250
    }];

    private myAggregate(values: number[], series: any, dataItems: Model[], category: string) {
        /* Return a sum of the values */
        return values.reduce((n, acc) => acc + n, 0);
    }
}
In this article